【HDU5656】CA Loves GCD,容斥思想与乱搞

Yveh
聪哥
传送门-BCの中文题面
传送门-HDU
写在前面:这次不准备写BC R78的解题报告了,为什么呢?因为题目太……由于那天正好休息,和Yveh分隔两地信息不通,结果分别用的自己的号打(xym-div2,Yveh-div1),结果xym在T1 WA了无数遍后终于A了,然后就和Yveh一起在T2被卡住了,多亏聪哥(the flash)救场在QQ上直接秒掉T2,挽救yveh与xym于水深火热,最终yveh只掉了13rating,xym也到达了1700+的rating可以打div1了,经过这次刻骨铭心的教训后,xym得出了一个重要结论:不和yveh坐在一起的时候绝不打BC(PS:两个人都Hack失败数次,没有一次成功)xym の OS:都是老油条,unsigned long long宏定义成LL……
思路:

【HDU5656】CA Loves GCD,容斥思想与乱搞_第1张图片
【HDU5656】CA Loves GCD,容斥思想与乱搞_第2张图片
代码:

#include<cstdio>
#include<cstring>
#define mod 100000007
using namespace std;
long long f[1010],g[1010]; 
long long ans=0;
int t,n,num[1010],a[1010];
long long quick_pow(int a,int x,int p)
{
    long long sum=a,ans=1;
    while (x>0)
    {
        if (x%2==1)
            ans=ans*sum%p;
        sum=sum*sum%p;
        x=x/2;
    }
    return ans;
}
void work()
{
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        memset(num,0,sizeof(num));
        for (int i=1;i<=n;i++)
            for (int j=1;j<=1000;j++)
                if (a[i]%j==0)
                    num[j]++;
        for (int i=1;i<=1000;i++)
            f[i]=quick_pow(2,num[i],mod)-1;
        for (int i=1000;i>=1;i--)
        {
            g[i]=f[i];
            for (int j=2;j*i<=1000;j++)
                g[i]=(g[i]-g[j*i]+mod)%mod;
        }
        ans=0;
        for (int i=1;i<=1000;i++)
            ans=(ans+g[i]*i%mod)%mod;
        printf("%I64d\n",ans);
    }
}
int main()
{
    work();
    return 0;
}

你可能感兴趣的:(【HDU5656】CA Loves GCD,容斥思想与乱搞)