【ContestHunter】【弱省胡策】【Round3】(C)
容斥原理+Fib
Orz HE的神犇们
蒟蒻只能改出来第三题……实在太弱
官方题解:http://pan.baidu.com/s/1o6MdtQq
fib的神奇性质……还有解密a[i]的过程……这里就不细说了……
主要学习了一下容斥>_<(然而还是没什么感觉?)
写在代码注释里了……
1 //Round3 C 2 #include<cstdio> 3 #include<set> 4 #include<cstring> 5 #include<cstdlib> 6 #include<iostream> 7 #include<algorithm> 8 #define rep(i,n) for(int i=0;i<n;++i) 9 #define F(i,j,n) for(int i=j;i<=n;++i) 10 #define D(i,j,n) for(int i=j;i>=n;--i) 11 #define pb push_back 12 using namespace std; 13 typedef long long LL; 14 inline int getint(){ 15 int r=1,v=0; char ch=getchar(); 16 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 17 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 18 return r*v; 19 } 20 const int N=2000010,M=5000010,P=1e9+7; 21 /*******************template********************/ 22 23 LL f[M],a[N],s[M],g[M]; 24 int n,w[M]; 25 inline LL gcd(LL a,LL b){return b ? gcd(b,a%b) : a;} 26 int main(){ 27 #ifndef ONLINE_JUDGE 28 freopen("C.in","r",stdin); 29 freopen("C.out","w",stdout); 30 #endif 31 n=getint(); LL mx=0; 32 F(i,1,n){ 33 int c=getint(),A,B; 34 if (c){ 35 A=getint(),B=getint(); 36 a[i]=(A+B-gcd(A,B)); 37 }else a[i]=getint(); 38 w[a[i]]++; 39 mx=max(mx,a[i]); 40 } 41 F(i,1,mx) 42 for(int j=i;j<=mx;j+=i) 43 s[i]+=w[j];//s[i]表示i的倍数一共出现了多少次(约数相关) 44 f[0]=f[1]=1; 45 F(i,2,mx){ 46 f[i]=f[i-1]+f[i-2]; 47 if (f[i]>=P) f[i]-=P; 48 } 49 LL ans=0; 50 F(i,1,mx) g[i]=s[i]*(s[i]-1)/2%P,ans+=f[i-1]*w[i]%P; 51 //g[i]表示有多少对a[i]和a[j]之间的gcd包含i这个因子 52 D(i,mx,1) 53 for(int j=i+i;j<=mx;j+=i) 54 g[i]-=g[j]; 55 //容斥的过程 56 //x作为gcd出现的次数=x作为公约数出现的次数-x的倍数作为gcd出现的次数 57 F(i,1,mx) ans+=g[i]*f[i-1]%P; 58 printf("%lld\n",(ans%P+P)%P); 59 return 0; 60 }