BZOJ 3884 上帝与集合的正确用法 欧拉定理

来源:互联网 发布:java二叉树的建立 编辑:程序博客网 时间:2024/05/06 15:51

题意:链接

方法:欧拉定理

解析:

首先你需要知道一个公式。

这里写图片描述

注意适用条件x>=Phi(C)

然而对于本道题来说x是无穷,所以可以直接上降幂公式解决。

证明

代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 3000010#define M 10000010using namespace std;typedef long long ll;ll t,p,tot;int prime[N],euler[M],v[M];void sieve(){    for(int i=2;i<=10000000;i++)    {        if(!v[i])        {            prime[++tot]=i;            euler[i]=i-1;        }        for(int j=1;j<=tot&&i*prime[j]<=10000000;j++)        {            v[i*prime[j]]=1;            if(i%prime[j]==0)            {                euler[i*prime[j]]=euler[i]*prime[j];                break;            }else            {                euler[i*prime[j]]=euler[i]*(prime[j]-1);            }        }    }}ll quick_my(ll x,ll y,ll mod){    ll ret=1;    while(y)    {        if(y&1)ret=(ret*x)%mod;        x=(x*x)%mod;        y>>=1;    }    return ret;}int check(ll x){    while(x%2==0)x/=2;    if(x==1)return 1;    return 0; }ll solve(ll x){    ll ret=0;    if(check(euler[x]))ret+=euler[x];    else ret+=solve(euler[x])+euler[x];    return quick_my(2,ret,x); }int main(){    sieve();    scanf("%lld",&t);    while(t--)    {        scanf("%lld",&p);        if(p==1){puts("0");continue;}        printf("%lld\n",solve(p));    }}
0 0
原创粉丝点击