[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 }

 

posted @ 2017-10-01 17:43  Elpsywk  阅读(178)  评论(0编辑  收藏  举报