• codeforce 906 SOL (D)


    一道数论题。这很像BZOJ的一道题,好像是P^P^P^P......(无穷多个P)mod M的值。

    我们知道当模数P是质数的时候,我们有  X^i=X^(i % p-1) (mod p)

    我们不妨对其扩展,得到 X^i=X^(i% φ(p)+ φ(p))(mod p)(i>φ(p))

    我们又可证φ(φ(p))<p/2 (从奇偶性进行考虑)

    那么我们定义函数sol(i,j,mo)为区间[i,j]在mo下的答案,

    我们定义指数上的mod运算 XmodY=(X>Y?X%Y+Y:X)

    那么我们有 sol(i,j,mo)=a[i] ^(sol(i+1,j,φ(mo)))//这里的快速幂是在mod意义下的。

    我们发现φ(mo)=1时便没有意义做下去了。那么我们一次询问要O(log N*log N)(一个log是给快速幂的)。

    #include<bits/stdc++.h>
    #define MOD(a,b) (a>b?(b)+(a)%(b):(a))
    #define sight(c) ('0'<=c&c<='9')
    #define LL long long
    #define N 200007
    using namespace std;
    int p[N],fi[N],pim[N>>1],tot,a[N],n,mo,l,r,m;
    map<int,int> mp;
    void pri(){
        for (int i=2;i<N;i++) {
            if (!p[i]) fi[i]=i-1,pim[++tot]=i;
            for (int j=1;j<=tot&&pim[j]*i<N;j++) {
                p[i*pim[j]]=pim[j];
                if (i%pim[j]) fi[i*pim[j]]=fi[i]*(pim[j]-1);
                else {fi[i*pim[j]]=fi[i]*pim[j]; break;}
            }
        }
    }
    int P(int k){  
        int s=k,x=k;  
        if (k<N) return fi[k];
        if (mp.count(k)) return mp[k];                 
        for(int i=2;i*i<=k;i++)  {  
            if(k%i==0) s=s/i*(i-1);  
            while(k%i==0) k/=i;  
        }  
        if(k>1) s=s/k*(k-1);  
        mp[x]=s; return s;  
    }
    inline void read(int &x){
        static char c;
        for (c=getchar();!sight(c);c=getchar());
        for (x=0;sight(c);c=getchar())x=x*10+c-48;
    }
    void write(LL x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
    inline void writeln(LL x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('
    '); }
    LL qsm(LL x,LL y,LL mo){
        static LL anw;
        for (anw=1;y;y>>=1,x=MOD(x*x,mo))if (y&1) anw=MOD(anw*x,mo);
        return anw;
    }
    LL sol(int l,int r,int mo){
        if (l==r||mo==1) return MOD(a[l],mo);
        return qsm(a[l],sol(l+1,r,P(mo)),mo);
    }
    int main () {
        freopen("d.in","r",stdin);
        pri();
        read(n); read(mo); 
        for (int i=1;i<=n;i++) read(a[i]);
        read(m);
        while (m--) {
            read(l),read(r);
            writeln(sol(l,r,mo)%mo);
        }return 0;
    }
  • 相关阅读:
    1月6日 作业 穷举
    1.4 作业
    12月31日 作业
    12月29日-练习成果
    12月30日作业-<转>字符集编码
    1.22作业
    集合
    泛型
    CPU接口练习 (仅以此程序证明 某个同学真的有毒!有毒!!!)
    继承知识点总结
  • 原文地址:https://www.cnblogs.com/rrsb/p/8298400.html
Copyright © 2020-2023  润新知