DU 5212
题意:给出长度为n的序列a,求定义f(i,j)为gcd(a[i],a[j])*(gcd(a[i],a[j])-1).
求f(i,j)的累加和[i=1..n,j=1...n] 答案模mod.
n,a[i]<=1e4,
直接遍历序列显然是TLE的.a[i]<=1e4 我们枚举每个数作为gcd时的贡献.
当x作为gcd 算出x的倍数有num个 则任选两个方案为num^2 .其中重复为gcd=2x,3x..kx产生的贡献
题意:给出长度为n的序列a,求定义f(i,j)为gcd(a[i],a[j])*(gcd(a[i],a[j])-1).
求f(i,j)的累加和[i=1..n,j=1...n] 答案模mod.
n,a[i]<=1e4,
直接遍历序列显然是TLE的.a[i]<=1e4 我们枚举每个数作为gcd时的贡献.
当x作为gcd 算出x的倍数有num个 则任选两个方案为num^2 .其中重复为gcd=2x,3x..kx产生的贡献
用dp[x]来记录x为gcd的实际(i,j)方案数,从大到小计算即可.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e4+5,mod=1e4+7;
int n,a[N];
ll dp[N],fre[N];
int main()
{
while(cin>>n)
{
int mx=0;
memset(fre,0,sizeof(fre));
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),mx=max(mx,a[i]),fre[a[i]]++;
ll ans=0;
for(int i=mx;i>=1;i--)
{
ll cnt=0,ex=0;
for(int j=i;j<=mx;j+=i)
cnt+=fre[j];
cnt=(cnt*cnt)%mod;
for(int j=i+i;j<=mx;j+=i)
ex=(ex+dp[j])%mod;
dp[i]=(cnt-ex+mod)%mod;
ans=(ans+dp[i]*i*(i-1)%mod)%mod;
}
printf("%lld\n",ans);
}
return 0;
}