Solution to a problem P4980 [[template]] Polya Theorem

[Template] Polya theorem of solution to a problem

A new algorithm. . .

First, we analyze the topic:

N points to a cycloalkyl FIG n colors, the number of programs to ask different nature

So, obviously, this is a polya Theorem (nonsense, title name says it all)

Let's take a look at this question of "action", it is clear that there is only one operation - translation (some say the rotation, but I personally prefer as a translation ...)

We can begin to enumerate the replacement

First, we enumerate each translation unit length, then it is clear that the different nature of translation there are n, respectively, translating 0- (n-1) th unit

Can be found in every translation program is a kind of replacement

Therefore, we can enumerate the length of the translation, stepping translation now assumed unit i, then the sequence is such that "shifted" back, we assume that a minimum of k steps. Then k must satisfy: i * k% n == 0, can solve for k = lcm (n, i) / i = n / gcd (n, i), so there are n / k = gcd (n, i) a "cycle", and therefore, according to polya theorem, the current substitution "fixed point" is the number of n (number of colors) ^ gcd (n, i), for shorthand, we put a lump to s [i].

Finally, the burnside lemma, we can know the program number of $ \ frac {sum_ {i = 0} ^ {n-1} s [i]} {n} $% $ mod $

So we can play Code:

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
inline int ksm(int x,int y,int z){
    int ans=1;
    while(y){
        if(y&1){
            ans=(1LL*ans*x)%z;
        }
        x=(1LL*x*x)%z;
        y>>=1;
    }
    return ans%z;
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        int ans=0;
        for(int i=0;i<n;++i){
            ans+=ksm(n,__gcd(n,i),mod);
            ans%=mod; 
        }
        ans=(1LL*ans*ksm(n,mod-2,mod))%mod;//逆元 
        printf("%d\n",ans);
    }
    return 0;
}

Then, it is the T. . . qwq

So, how can we optimize this program do?

The following is the text ---------------- ------------------

We can easily notice, to make gcd (n, i) the same i, the contribution of the answer is the same (first whether divided by n), as n ^ gcd (n, i), then we may wish to enumerate gcd (n, i)!

Because enumeration gcd about the number (n, i) n is equivalent to enumeration, so we complexity of the enumeration part of it down to the $ O (\ sqrt {n}) $, so now we need to do is try to calculate this problem quickly:

About a given number of n i, and the number of seek 0- GCD of n number (n-1), there is i

We first case i = 1 and i = n is calculated (for convenience).

i = 1, satisfies the condition of a total of φ (n) th, i = n-a when a (gcd (0, n) = n)

Therefore, both the answer and to Ans1 = (φ (n) * n + n ^ n)% mod

So, let us look at how the rest of the count

We have found, seek 0- (n-1) number of how many of the n-i gcd is, since n and i is not equal to 1, so the problem is equivalent to

Seeking how much 1-n and n gcd is the number i.

And we can see that the condition must be a multiple of the number of i. Therefore, the problem is equivalent to: enumerate 1-n / i, how many number j satisfies gcd (n, j * i) = i

Is equivalent to finding 1-n / i how many number j satisfies gcd (n / i, j) = 1, it is clear that the answer to this question is φ (n / i)

(Why so much conversion step ah! Crazy ing ...)

So, we need a faster seek φ (x) of

Originally, we can pre-obtained all φ with O (n) time, but the problem is n <= 1e9, if good time, then, presumably card too, but obviously does not allow the space, so, we must find a better way.

We know, φ is a multiplicative function, so we can according to its nature, to find one of its prime factors, then recursive solution. . .

Referring to teach Du screen, we can first pre-smaller φ out (I was pretreated to 1e7)

Then, we first determine whether the use Miller_rabin algorithm x is a prime number, and if so, we will return to x-1, otherwise, we can use pollard_rho algorithm to decompose x, recursive solution, the middle set of a map can be accelerated. Problems have solutions.

Of course, I remember especially under sentence answer n = 1 (since the beginning we counted the same time i = 1 and i = n the answer, then to 1, the more calculations a)

Semi pseudocode:

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7,N=1e7+1;
map<int,int>f;
int T,fi[N],zhi[N>>1],e;
inline int ksm(int x,int y,int z){
    int ans=1;
    while(y){
        if(y&1){
            ans=(1LL*ans*x)%z;
        }
        x=(1LL*x*x)%z;
        y>>=1;
    }
    return ans;
}
inline void sai(int maxe){
    T=maxe;fi[1]=1;
    for(int i=2;i<=maxe;++i){
        if(!fi[i]){
            fi[i]=i-1;zhi[++e]=i;
        }
        for(int j=1;j<=e;++j){
            if(i*zhi[j]>maxe){
                break;
            }
            if(i%zhi[j]==0){
                fi[i*zhi[j]]=fi[i]*zhi[j];
                break;
            }
            fi[i*zhi[j]]=fi[i]*fi[zhi[j]];
        }
    }
}
inline bool Miller_rabin(int x){
    //偷懒省略 
}
inline int pollard_rho(int x){
    //偷懒省略 
}
inline int calc(int x){
    if(x<=T){
        return fi[x];
    }
    if(f.find(x)!=f.end()){
        return f[x];
    }
    int ret=pollard_rho(x);
    if(ret==x){
        return x-1;
    }
    return f[x]=((x/ret)%ret==0?ret*calc(x/ret):(ret-1)*calc(x/ret));
}
int main(){
    srand(1);
    sai(1e7);//预处理 
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n); 
        if(n==1){
            puts("1");
            continue;
        }
        int ans=(ksm(n,n,mod)+(1LL*n*calc(n))%mod)%mod;
        for(int i=sqrt(n);i>=2;--i){//一次平移的距离
            if(n%i==0){
                ans+=(1LL*ksm(n,i,mod)*calc(n/i))%mod;
                ans%=mod;
                if(n/i!=i){
                    ans+=(1LL*ksm(n,n/i,mod)*calc(i))%mod;
                    ans%=mod;
                }
            }
        }
        ans=(1LL*ans*ksm(n,mod-2,mod))%mod;//逆元 
        printf("%d\n",ans);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/ThinkofBlank/p/11527113.html