zoukankan      html  css  js  c++  java
  • 题解 poj 2154 Color

    传送门


    【题意】

    (x) 组数据

    每组询问 (n) 个颜色填涂 (n) 个空位的环,问不同构方案数,答案对 (p) 取模。

    规定某个环能被另一个环旋转得到时,这两个环同构。

    (xleq 3500, nleq 10^9)


    【分析】

    显然 (n) 个角度的旋转构成一个群,根据 polya 定理,得到答案为:

    (displaystyle {1over n}sum_{i=1}^n n^{gcd(i, n)}={1over n}sum_{dmid n} n^d oldsymbol varphi({nover d})=sum_{dmid n} n^{d-1} oldsymbol varphi({nover d}))

    但如果暴力计算每一个 (oldsymbol varphi({nover d})) 复杂度为 (O(n^{3over 4})) 可能不够,考虑先打出前 ({n^{3over 5}}) 个欧拉函数值,则求解所有欧拉函数的复杂度降低为 (O(n^{3over 5}))(证明如下)

    故求解一组的复杂度为 (O(n^{3over 5})+O(sqrt n)+O(sqrt nlog n)=O(n^{3over 5})),总复杂度即为 (O(xcdot n^{3over 5})),卡卡常能过


    【代码】

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<ll, ll> pii;
    typedef double db;
    #define fi first
    #define se second
    int n, mod;
    inline int fpow(int a,int x) { ll ans=1; for(;x;x>>=1,a=(ll)a*a%mod) if(x&1) ans=(ll)ans*a%mod; return ans; }
    const int Lim=2.6e5, MAXN=Lim+10;
    int fc[MAXN], phi[MAXN], prime[MAXN], cntprime;
    inline int getphi(int n) {
        if(n<=Lim) return phi[n];
        int val=n;
        for(int j=1;j<=cntprime;++j)
            if((ll)prime[j]*prime[j]>n) break;
            else if(n%prime[j]==0){
                val=val/prime[j]*(prime[j]-1);
                while(n%prime[j]==0) n/=prime[j];
            }
        if(n!=1) val=val/n*(n-1);
        return val;
    }
    inline int ans(){
        int res=0;
        for(int i=1;i*i<=n;++i) if(n%i==0) {
            int j=n/i;
            res+=(ll)getphi(j)*fpow(n, i-1)%mod;
            res-=(res>=mod?mod:0);
            if(i!=j){
                res+=(ll)getphi(i)*fpow(n, j-1)%mod;
                res-=(res>=mod?mod:0);
            }
        }
        return res;
    }
    inline void sieve(){
        phi[1]=1;
        for(int i=2;i<=Lim;++i){
            if(!fc[i]) fc[i]=prime[++cntprime]=i, phi[i]=i-1;
            for(int j=1;j<=cntprime;++j)
                if(prime[j]*i>Lim||prime[j]>fc[i]) break;
                else fc[prime[j]*i]=prime[j], phi[prime[j]*i]=phi[i]*(prime[j]-(prime[j]!=fc[i]));
        }
    }
    int main(){
        ios::sync_with_stdio(0);
        cin.tie(0); cout.tie(0);
        sieve();
        int x; cin>>x;
        while(x--&&cin>>n>>mod) cout<<ans()<<"
    ";
        cout.flush();
        return 0;
    }
    

    【证明】

    朴素求解所有欧拉函数的复杂度求解如下考虑:

    由于每个数字 (n) ,设其存在一个严格小于 (sqrt n) 的因数 (d) ,则必然同时存在一严格大于 (sqrt n) 的因数 ({nover d})

    故因数个数至多为 (2cdot(sqrt n-1)+1=2sqrt n-1)

    我们朴素求解 (n) 的欧拉函数值,复杂度为 (O(sqrt n))

    (displaystyle T(n)=sum_{dmid n}Ccdot sqrt dleq Csum_{d=1}^{sqrt n}(sqrt d+sqrt {nover d}))

    由于 (displaystyle sum_{x=1}^{sqrt n} sqrt xapprox int_1^{sqrt n}x^{1over 2} ext dx={2over 3}(x^{3over 2}|^{sqrt n}_1)=O(n^{3over 4}))

    (displaystyle sum_{x=1}^{sqrt n} {1over sqrt x}approx int_1^{sqrt n} x^{-{1over 2}} ext dx=2(x^{1over 2}|^{sqrt n}_1)=O(n^{1over 4}))

    (T(n)=Ccdot O(n^{3over 4})+Ccdot sqrt ncdot O(n^{1over 4})=O(n^{3over 4}))

    此为朴素计算的复杂度

    考虑有限筛出 (m) 范围内欧拉函数的值,由上述朴素的分析得到:

    (m<sqrt n) ,则前半部分时间复杂度减小,后半部分不变,总复杂度为 (O(m)+o(n^{3over 4})+O(n^{3over 4})=O(n^{3over 4}))

    (mgeq sqrt m),此时可得,后半部分的因数均大于 (m),故其对应的小因数均小于 ({nover m})

    故复杂度化为 (displaystyle T(n)=O(m)+sum_{i=1}^{nover m}Ccdot sqrt{nover i}=O(m)+Ccdot sqrt ncdot O(({nover m})^{1over 4})=O(m)+O({n^{3over 4}over m^{1over 4}}))

    (displaystyle T(n)=C_1m+C_2cdot {n^{3over 4}over m^{1over 4}})

    根据均值不等式,(displaystyle C_1m=C_2cdot {n^{3over 4}over m^{1over 4}})(T(n)) 取最小值,达到 (O(m))

    求解等式得到 (m=({C_2over C_1})^{4over 5}cdot n^{3over 5})

    由于我也不知道 (C_1, C_2) 的值,故均取 (1),得到 (T(n)=O(m)=O(n^{3over 5}))

  • 相关阅读:
    Aurora 数据库支持多达五个跨区域只读副本
    Amazon RDS 的 Oracle 只读副本
    Amazon EC2 密钥对
    DynamoDB 读取请求单位和写入请求单位
    使用 EBS 优化的实例或 10 Gb 网络实例
    启动 LAMP 堆栈 Web 应用程序
    AWS 中的错误重试和指数退避 Error Retries and Exponential Backoff in AWS
    使用 Amazon S3 阻止公有访问
    路由表 Router Table
    使用MySQLAdmin工具查看QPS
  • 原文地址:https://www.cnblogs.com/JustinRochester/p/14994213.html
Copyright © 2011-2022 走看看