zoukankan      html  css  js  c++  java
  • Sum of gcd of Tuples【容斥定理】

    题意:

      考虑长度为 (N) 且由 (1)(K) 之间的整数组成的序列 ({A_1,...,A_N})(包括 (K))。有 (K^N) 个这样的序列,求出 (gcd(A_1,...,A_N)) 的总和。由于此总和可能非常大,因此请取模 (10^9+7)
    传送门

    分析:

      以 (dp[i]) 表示 (gcd)(i) 的序列个数,([1,k])(i) 的倍数的个数为 (lfloor frac{k}{i} floor)。序列总数为:({lfloor frac{k}{i} floor}^n),同时由于会出现重复,所以要减去 (gcd)(i*2,i*3,...) 的情况,循环要从大到小。
      一开始直接减,发现有一部分多减了(具体见代码注释部分)。即当两个数均为 (i) 的倍数且倍数互质,那么二者的 (gcd) 仍为 (i),即序列中不一定要出现 (i)

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=1e9+7;
    const int N=1e5+5;
    ll dp[N];
    ll power(ll a,ll b)
    {
        ll res=1;
        while(b)
        {
            if(b&1)
                res=res*a%mod;
            a=a*a%mod;
            b>>=1;
        }
        return res%mod;
    }
    int main()
    {
        int n,k;
        ll ans=0;
        scanf("%d%d",&n,&k);
        for(int i=k;i>=1;i--)//以i为gcd
        {
            int tk=k/i;
            dp[i]=power(1LL*tk,1LL*n);
            for(int j=i*2;j<=k;j+=i)
                dp[i]-=dp[j];
            //ll t=power(1LL*tk,1LL*n)-power(1LL*(tk-1),1LL*n);cout<<i<<"="<<t<<endl;
            ans=(ans+dp[i]*i%mod+mod)%mod;//cout<<ans<<endl;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    TuShare接口适应
    任泽平金句记录
    分红送股---要注意的两个日期
    解决github无法登录的问题
    持久斗争
    正则语法
    JWT的结构
    付鹏的黄金分析框架
    vscode设置背景图片
    Ubuntu 16.04安装Nginx
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/12719002.html
Copyright © 2011-2022 走看看