zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    LeetCode 40. 组合总和 II(Combination Sum II)
    LeetCode 129. 求根到叶子节点数字之和(Sum Root to Leaf Numbers)
    LeetCode 60. 第k个排列(Permutation Sequence)
    LeetCode 47. 全排列 II(Permutations II)
    LeetCode 46. 全排列(Permutations)
    LeetCode 93. 复原IP地址(Restore IP Addresses)
    LeetCode 98. 验证二叉搜索树(Validate Binary Search Tree)
    LeetCode 59. 螺旋矩阵 II(Spiral Matrix II)
    一重指针和二重指针
    指针的意义
  • 原文地址:https://www.cnblogs.com/Livingston/p/15758483.html
Copyright © 2011-2022 走看看