线性求逆元

线性求逆元
1.这是求1~n
i的逆元为i^(-1) (mod p)
我令p=k*i+r,0<i<p,r<i
p=0(mod p)
k*i+r=0(mod p)
两边同时乘(i^(-1))*(r^(-1)),然后移项
i^(-1)=-k*r^(-1)(mod p)
i^(-1)=-(p/i)*(p%i)^(-1)(mod p)
故a[i]表示i的逆元
a[i]=-(p/i)*a[p%i](mod p)两边同时+p*(a[p%i])-->主要是为了保证是正数
a[i]+p*(a[p%i])=p-(p/i)*a[p%i](mod p)
又因为p*(a[p%i])=0(mod p)
a[i]=(p-p/i)*a[p%i](mod p)

2.求任意n个数的逆元
主要利用的性质是,积的逆元等于逆元的积

#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cstring>
#define inf 2147483647
#define N 3000010
#define p(a) putchar(a)
#define For(i,a,b) for(long long i=a;i<=b;++i)
//by war
//2019.8.7
using namespace std;
long long n,p;
long long s[N],inv[N],sv[N];
void in(long long &x){
    long long y=1;char c=getchar();x=0;
    while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
    while(c<='9'&&c>='0'){ x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    x*=y;
}
void o(long long x){
    if(x<0){p('-');x=-x;}
    if(x>9)o(x/10);
    p(x%10+'0');
}

long long ksm(long long a,long long b){
    long long r=1;
    while(b>0){
        if(b&1)
            r=r*a%p;
        a=a*a%p;
        b>>=1;
    }
    return r;
}

signed main(){
    in(n);in(p);
    s[0]=1;
    For(i,1,n)
        s[i]=s[i-1]*i%p;
    sv[n]=ksm(s[n],p-2);
    for(long long i=n;i;i--)
        sv[i-1]=sv[i]*i%p;
    For(i,1,n)
        o(s[i-1]*sv[i]%p),p('
');
    return 0;
}
原文地址:https://www.cnblogs.com/war1111/p/7684108.html