zoukankan      html  css  js  c++  java
  • 洛谷 P5221 Product

    ({ m CYJian})最近闲的玩起了(gcd)。。他想到了一个非常简单而有意思的式子:

    [prod_{i=1}^Nprod_{j=1}^Nfrac{lcm(i,j)}{gcd(i,j)} (mod 104857601) ]

    ({ m CYJian})已经算出来这个式子的值了。现在请你帮他验算一下吧。({ m CYJian})只给你(0.2s)的时间哦。

    (1 leq N leq 1000000)


    把式子写成:

    [=prod_{i=1}^Nprod_{j=1}^Nfrac{ij}{gcd^2(i,j)}=frac{prod_{i=1}^Nprod_{j=1}^Nij}{(prod_{i=1}^Nprod_{j=1}^Ngcd(i,j))^2} ]

    上面的部分就是 ((N!)^{2N}) ,对于下面 (prod_{i=1}^Nprod_{j=1}^Ngcd(i,j)) 部分,考虑枚举 (gcd) 是多少,设 (g(x,n)) 表示 (sum_{i=1}^nsum_{j=1}^n[gcd(i,j)==x]) ,那么这个式子就变成了:

    [prod_{i=1}^Ni^{g(i,N)} ]

    考虑怎么求所有的 (g(i,N)) ,我们写出式子:

    [egin{aligned}g(x,n)&=sum_{i=1}^nsum_{j=1}^n[gcd(i,j)==x]\&=sum_{i=1}^{frac{n}{x}}sum_{j=1}^{frac{n}{x}}[gcd(i,j)==1]\&=g(1,frac{n}{x})end{aligned} ]

    然后考虑求 (g(1,n)) ,就有:

    [egin{aligned} g(1,n)&=sum_{i=1}^{n}sum_{j=1}^{n}sum_{d|gcd(i,j)}mu(d)\&=sum_{d=1}^nsum_{i=1}^{frac{n}{d}}sum_{j=1}^{frac{n}{d}}mu(d)\&=sum_{d=1}^nlfloorfrac{n}{d} floorlfloorfrac{n}{d} floormu(d)end{aligned}]

    这个可以整除分块 (sqrt{n}) 完成。

    然后现在我们要求:

    [prod_{i=1}^Ni^{g(1,frac{N}{i})} ]

    (frac{N}{i}) 也整除分块,这样就可以做到 (O(N+sqrt Nlog N)) 的复杂度处理出来了。

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    const int N = 1e6;
    const int M = 1e5;
    const int p = 104857601;
    using namespace std;
    int n,mul[N + 5],prime[M + 5],pcnt,ans,s;
    bool vis[N + 5];
    int mypow(int a,long long x){int s = 1;for (;x;x & 1 ? s = 1ll * a * s % p : 0,a = 1ll * a * a % p,x >>= 1);return s;}
    long long calc(int n)
    {
        long long ans = 0;
        for (int l = 1,r;l <= n;l = r + 1)
        {
            r = n / (n / l);
            ans += 1ll * (n / l) * (n / l) * (mul[r] - mul[l - 1]);
        }
        return ans;
    }
    void prework()
    {
        vis[1] = 1;mul[1] = 1;
        for (int i = 2;i <= n;i++)
        {
            if (!vis[i])
            {
                mul[i] = -1;
                prime[++pcnt] = i;
            }
            for (int j = 1;j <= pcnt && prime[j] * i <= n;j++)
            {
                vis[prime[j] * i] = 1;
                mul[prime[j] * i] = -mul[i];
                if (i % prime[j] == 0)
                {
                    mul[prime[j] * i] = 0;
                    break;
                }
            }
        }
        for (int i = 1;i <= n;i++)
            mul[i] += mul[i - 1];
    }
    int main()
    {
        scanf("%d",&n);
        prework();
        ans = 1;
        for (int i = 1;i <= n;i++)
            ans = 1ll * ans * i % p;
        ans = mypow(ans,n);
        ans = 1ll * ans * ans % p;
        s = 1;
        for (int l = 1,r;l <= n;l = r + 1)
        {
            r = n / (n / l);
            int tmp = 1;
            for (int i = l;i <= r;i++)
                tmp = 1ll * tmp * i % p;
            s = 1ll * s * mypow(tmp,calc(n / l)) % p;
        }
        s = 1ll * s * s % p;
        ans = 1ll * ans * mypow(s,p - 2) % p;
        cout<<(ans + p) % p<<endl;
        return 0;
    }
    
  • 相关阅读:
    中国剩余定理
    【BZOJ】【3053】The Closest M Points
    【BZOJ】【1878】【SDOI2009】HH的项链
    【BZOJ】【2648】SJY摆棋子&【BZOJ】【2716】【Violet 3】天使玩偶
    【UOJ Easy Round #2】
    【TYVJ 五月图论专项有奖比赛】
    【BZOJ】【3301】【USACO2011 Feb】Cow Line
    【BestCoder】【Round#41】
    【BZOJ】【1046】/【POJ】【3613】【USACO 2007 Nov】Cow Relays 奶牛接力跑
    【BZOJ】【3210】花神的浇花集会
  • 原文地址:https://www.cnblogs.com/sdlang/p/14306960.html
Copyright © 2011-2022 走看看