4668. 【NOIP2016提高A组模拟7.19】腐败

Description

识时务者,俊杰上课没事干,腐起败来。他磨着你给他解决一道题:
给你一个长度为n 序列 A,求 \(\prod_{i=1}^{n} \prod_{j=i}^{n} \gcd(A[i], A[j])\)
即从序列中选两个数 i,j 出来, 满足 i\(\le\)j,求他们 gcd,记为 k 。然后把所有情况的 i 和 j 对应的 k 给乘起来。
答案太大了,请你对 100000000009 取模。
小心点,这个模数很奇怪。

Solution

对于每个数来计算贡献是不行的,考虑对于每个质因数计算贡献。

\(\mathrm{vector}\) 来记录每个质因数的指数序列。

统计出每个质因数的指数序列后,排序,那么对于一个质因数的指数序列,前面的数和后面的数的 \(\gcd\) 在当前这个质因数上的贡献是 \(p^{\sum x}\)\(p\) 表示当前这个质因数,\(\sum x\) 是指此前的指数前缀和)。

另外,对于指数序列全是 1 的质因数,可以直接 \(\mathcal O(1)\) 计算。

Code

#include<cstdio>
#include<vector>
#include<algorithm>
#define N 40005
#define M 1000005
#define mod 100000000009
#define inf 12345678  
#define ll long long
using namespace std;
vector<ll> pr[M];
int n,num,bj[inf];
ll ans,a[N],p[N];
ll ksc(ll x,ll y)
{
    ll x1=x/inf,x2=x%inf,y1=y/inf,y2=y%inf;
    ll res=0;
    res=(res+x1*y1%mod*inf%mod*inf%mod)%mod;
    res=(res+x1*inf%mod*y2%mod)%mod;
    res=(res+x2*y1%mod*inf%mod)%mod;
    res=(res+x2*y2%mod)%mod;
    return res;
}
ll ksm(ll x,ll y)
{
    ll res=1;
    while (y)
    {
        if (y&1) res=ksc(res,x)%mod;
        x=ksc(x,x)%mod;
        y>>=1;
    }
    return res;
}
void fenjie(ll x)
{
    for (int i=2;i*i<=x;++i)
    {
        if (x%i!=0) continue;
        if (!bj[i]) p[++num]=i,bj[i]=num;
        int s=0;
        while (x%i==0) x/=i,++s;
        pr[bj[i]].push_back(s);
    }
    if (x>1)
    {
        if (!bj[x]) p[++num]=x,bj[x]=num;
        pr[bj[x]].push_back(1);
    }
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;++i)
        scanf("%lld",&a[i]),fenjie(a[i]);
    ans=1;
    for (int i=1;i<=num;++i)
    {
        if (p[i]*p[i]<=inf)
        {
            int len=pr[i].size();
            sort(pr[i].begin(),pr[i].end());
            ll sum=0;
            for (int j=0;j<len;++j)
            {
                ans=ksc(ans,ksm(p[i],sum));
                sum+=pr[i][j];
            }
        }
        else
        {
            ll len=pr[i].size();
            ans=ksc(ans,ksm(p[i],len*(len-1)/2));
        }
    }
    for (int i=1;i<=n;++i)
        ans=ksc(ans,a[i]);
    printf("%lld\n",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/Livingston/p/15758483.html