[pe531]Chinese leftovers
题意:1e6~1e6+5000之间任意两个之间同余方程组的解。余数为欧拉函数。
解题关键:线性筛预处理,扩展中国剩余定理暴力求解。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cmath> 6 #include<iostream> 7 #define MAXN 1005002 8 using namespace std; 9 typedef long long ll; 10 ll x,y,r[MAXN],m[MAXN],n; 11 12 //将求素数和欧拉函数值都线性解出 13 int prime[MAXN];//保存素数 14 bool vis[MAXN];//初始化 15 int phi[MAXN];//欧拉函数 16 void Lphisieve(int n){ 17 int cnt=0; 18 for(int i=2;i<n;i++){ 19 if(!vis[i]){ 20 prime[cnt++]=i; 21 phi[i]=i-1;// if p is prime,then phi[i]=i-1 22 } 23 for(int j=0;j<cnt&&i*prime[j]<n;j++){ 24 int k=i*prime[j]; 25 vis[k]=true; 26 if(i%prime[j]==0){ 27 phi[k]=phi[i]*prime[j]; 28 break; 29 } 30 else phi[k]=phi[i]*(prime[j]-1); 31 } 32 } 33 } 34 35 ll extgcd(ll a,ll b,ll &x,ll &y){ 36 ll d=a; 37 if(b) d=extgcd(b,a%b,y,x),y-=a/b*x; 38 else x=1,y=0; 39 return d; 40 } 41 ll excrt(int n,ll *m,ll *r){ 42 ll M=m[0],pre=r[0],d;//a是模数 43 for(int i=1;i<n;i++){ 44 d=extgcd(M,m[i],x,y); 45 if((pre-r[i])%d!=0) return -1; 46 x=(pre-r[i])/d*x%m[i]; 47 pre-=x*M; 48 M=M/d*m[i];//lcm 49 pre%=M; 50 } 51 return (pre%M+M)%M; 52 } 53 int main(){ 54 Lphisieve(1005001); 55 ll sum=0; 56 for(ll i=1000000;i<1005000;i++){ 57 m[0]=i,r[0]=phi[i]; 58 for(ll j=i+1;j<1005000;j++){ 59 m[1]=j,r[1]=phi[j]; 60 ll t=excrt(2,m,r); 61 if(t==-1) t=0; 62 sum+=t; 63 } 64 } 65 printf("%lld\n",sum); 66 }