HDU 5212

6 篇文章 0 订阅
1 篇文章 0 订阅

来自我的新博客

HDU 5212

Description:

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

Ans=i=1Nj=1Ngcd(ai,aj)(gcd(ai,aj)1) Mod 10007  (1<=ai,N<=10000)

      
      
      

Solution:

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

       那么 Ans=10000i=110000j=1num[i]num[j]gcd(i,j)(gcd(i,j)1)

       我们 f(i)=i(i1) ,并且构造函数 fr(d) 使得 f(i)=d|ifr(d)

       所以 Ans=10000i=110000j=1num[i]num[j]d|i,d|jfr(d)

                       ` =10000d=1d|id|jnum[i]num[j]fr(d)=10000d=1fr(d)(d|inum[i])2

       最终

Ans=d=110000fr(d)(i=110000dnum[id])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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值