zoukankan      html  css  js  c++  java
  • 【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
    ",(ans%P+P)%P);
    59     return 0;
    60 }
    View Code
  • 相关阅读:
    线段树
    坐标离散化
    超大背包问题
    折半枚举 双向搜索
    弹性碰撞
    反转 开关问题
    尺取法
    二分法
    最小生成树
    区间素数筛法
  • 原文地址:https://www.cnblogs.com/Tunix/p/4555282.html
Copyright © 2011-2022 走看看