【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 }
View Code

 

posted @ 2015-06-05 17:59  Tunix  阅读(211)  评论(0编辑  收藏  举报