bzoj3884 上帝与集合的正确用法

题意:求2^2^2^2^2.......^2%p的值,T组询问。

欧拉降幂多用几次就好了。

顺便试了下fwrite输出优化 ,效果显著。

#include<cstring>
#include<iostream>
#include<cctype>
#include<cstdio>
#define writ(x,c) write(x),push(c);
using namespace std;
inline char nc()
{
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    char c;int x=0;bool f=0;
    for(; !isdigit(c); c=nc()) if(c=='-') f=1;
    for(; isdigit(c); c=nc()) x=(x<<1)+(x<<3)+c-48;
    return (f ? -x : x);
}
char pbuf[100000],*pp=pbuf;
void push(const char c)
{
    if(pp-pbuf==100000) fwrite(pbuf,1,100000,stdout),pp=pbuf;
    *pp++=c;
}
void write(int x)
{
    static int sta[35];
    int top=0;
    do{sta[top++]=x%10,x/=10;}while(x);
    while(top) push(sta[--top]+'0');
}
const int M=1001001;
int phi[M],prime[M],tot;
bool not_prime[M];
inline int Phi(int x)
{
    int i,re=x;
    for(i=2; i*i<=x; i++)
        if(x%i==0)
        {
            re/=i;
            re*=i-1;
            while(x%i==0)
                x/=i;
        }
    if(x^1) re/=x,re*=x-1;
    return re;
}
inline int KSM(long long x,int y,int p)
{
    long long res=1;
    while(y)
    {
        if(y&1) (res*=x)%=p;
        (x*=x)%=p;
        y>>=1;
    }
    return res%p;
}
inline int calc(int p)
{
    if(p==1) return 0;
    int tmp=0,cur,res;
    while(~p&1) p>>=1,++tmp;
    cur=Phi(p);
    res=calc(cur);
    (res+=cur-tmp%cur)%=cur,res=KSM(2,res,p);
    return res<<tmp;
}
int main()
{
    register int T=read(),p;
    while(T--)
    {
        p=read();
        writ(calc(p),'\n');
    }
    fwrite(pbuf,1,pp-pbuf,stdout);
}

 

posted @ 2018-10-12 10:00  _hcy_a  阅读(226)  评论(0编辑  收藏  举报