题意:
考虑长度为 \(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} \rfloor\)。序列总数为:\({\lfloor \frac{k}{i} \rfloor}^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\n",ans);
return 0;
}