您的位置:首页 > 其它

HDU 5212

2015-09-15 21:39 423 查看
来自我的新博客

HDU 5212

Description:

~~~~~~ 给定一个数列{aN}\{a_N\} ,然后求

Ans=∑i=1N∑j=1Ngcd(ai,aj)∗(gcd(ai,aj)−1) Mod 10007 (1<=ai,N<=10000)Ans=\sum_{i=1}^{N}\sum_{j=1}^{N}gcd(a_i,a_j)*(gcd(a_i,a_j)-1)~Mod~10007~~(1<=a_i,N<=10000)

~~~~~~

~~~~~~

~~~~~~

Solution:

~~~~~~首先我们令 num[t]num[t] 表示 tt 这个数字在数列 {aN}\{a_N\} 中出现的次数。

~~~~~~那么 Ans=∑10000i=1∑10000j=1num[i]∗num[j]∗gcd(i,j)∗(gcd(i,j)−1)Ans=\sum_{i=1}^{10000}\sum_{j=1}^{10000}num[i]*num[j]*gcd(i,j)*(gcd(i,j)-1)

~~~~~~我们 令f(i)=i∗(i−1)令f(i)=i*(i-1) ,并且构造函数 fr(d)fr(d) 使得 f(i)=∑d|ifr(d)f(i)=\sum_{d|i}fr(d)

~~~~~~所以 Ans=∑10000i=1∑10000j=1num[i]∗num[j]∗∑d|i,d|jfr(d)Ans=\sum_{i=1}^{10000}\sum_{j=1}^{10000}num[i]*num[j]*\sum_{d|i,d|j}fr(d)

~~~~~~~~~~~~~~~~~~~~~~`=∑10000d=1∑d|i∑d|jnum[i]∗num[j]∗fr(d)=∑10000d=1fr(d)(∑d|inum[i])2=\sum_{d=1}^{10000}\sum_{d|i}\sum_{d|j}num[i]*num[j]*fr(d)=\sum_{d=1}^{10000}fr(d)(\sum_{d|i}num[i])^2

~~~~~~最终

Ans=∑d=110000fr(d)(∑i=1⌊10000d⌋num[i∗d])2Ans=\sum_{d=1}^{10000}fr(d)(\sum_{i=1}^{\left \lfloor \frac{10000}{d}\right \rfloor}num[i*d])^2

~~~~~~fr(d)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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: