HDU 5212
Description:
给定一个数列
{aN}
,然后求
Ans=∑i=1N∑j=1Ngcd(ai,aj)∗(gcd(ai,aj)−1) Mod 10007 (1<=ai,N<=10000)
Solution:
首先我们令
num[t]
表示
t
这个数字在数列
那么 Ans=∑10000i=1∑10000j=1num[i]∗num[j]∗gcd(i,j)∗(gcd(i,j)−1)
我们 令f(i)=i∗(i−1) ,并且构造函数 fr(d) 使得 f(i)=∑d|ifr(d)
所以 Ans=∑10000i=1∑10000j=1num[i]∗num[j]∗∑d|i,d|jfr(d)
` =∑10000d=1∑d|i∑d|jnum[i]∗num[j]∗fr(d)=∑10000d=1fr(d)(∑d|inum[i])2
最终
Ans=∑d=110000fr(d)(∑i=1⌊10000d⌋num[i∗d])2
fr(d) 怎么求?直接根据前面的定义式莫比乌斯反演就行了。
Code:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
const int Mod=10007;
int N;
int a[10010]={0};
int F[10010]={0};
int fr[10010]={0};
int main()
{
for(int i=1;i<=10000;i++)
{
fr[i]=(fr[i]+i*(i-1)%Mod)%Mod;
for(int j=i+i;j<=10000;j+=i)
fr[j]=(fr[j]+Mod-fr[i])%Mod;
}
for(;scanf("%d",&N)!=EOF;)
{
for(int i=1;i<=N;i++)
{
scanf("%d",&a[i]);
F[a[i]]++;
}
int ans=0;
for(int d=1;d<=10000;d++)
{
int sum=0;
for(int i=10000/d;i>=1;i--)
sum=(sum+F[i*d])%Mod;
ans=(ans+sum*sum%Mod*fr[d])%Mod;
}
printf("%d\n",ans);
memset(F+1,0,sizeof(int)*10000);
}
return 0;
}