HDU4335 What is N? [数论(欧拉函数)]

  这就是大神口中的简单题,我的数论简直烂到不行,这些数学出身的家伙何必出这些恶心的数学题来难为我们呢。。

  用到一个公式 A^x%P=(A^(x%phi(P)+phi[P]))%P (x>=phi[C]),phi[C]表示欧拉函数。

  注意条件是x>=phi[C],但这题的x是增长很快的,很快就能满足这个条件,所以x<phi[C]这部分暴力即可。

  接着继续暴力求x%phi[C]!=0的情况,很快就会出现x%phi[C]==0,并且之后一直都会满足,题目转化为求A^phi[P]%P==b,根据鸽巢原理,一定会出现长度为P循环节,于是统计循环节内满足条件的数的个数,再乘以循环节个数,然后在暴力统计一下多余长度内有多少个数满足条件即可。

  一个很大的trick就是结果会超LongLong,达到2^64,这里需要特判。。

 1 #include <string.h>
 2 #include <stdio.h>
 3 #define MAXN 100005
 4 typedef unsigned long long ULL;
 5 int cas;
 6 ULL m,ans,n,fac,tot,b,p;
 7 ULL phi[MAXN],mod[MAXN];
 8 //A^x%P=A^(x%phi(P)+phi[P])%P (x>=phi[C])
 9 void init(){
10     for(int i=1;i<MAXN;i++)phi[i]=i;
11     for(int i=2;i<MAXN;i+=2)phi[i]/=2;
12     for(int i=3;i<MAXN;i+=2)if(phi[i]==i){
13         for(int j=i;j<MAXN;j+=i)phi[j]=phi[j]/i*(i-1);
14     }
15 }
16 ULL pow(ULL a,ULL x){
17     ULL ret=1;
18     for(ULL tmp=a;x;x>>=1){
19         if(x&1){
20             ret*=tmp;
21             if(ret>=p)ret%=p;
22         }
23         tmp*=tmp;
24         if(tmp>=p)tmp%=p;
25     }
26     return ret;
27 }
28 int main(){
29     //freopen("test.in","r",stdin);
30     init();
31     scanf("%d",&cas);
32     for(int ca=1;ca<=cas;ca++){
33         scanf("%I64u%I64u%I64u\n",&b,&p,&m);
34         //TRICK! p==1&&c==0&&m=2^64-1 溢出
35         if(m==18446744073709551615ULL&&p==1ULL&&b==0ULL){
36             printf("Case #%d: 18446744073709551616\n",ca);
37             continue;
38         }
39         ans=n=tot=0,fac=1;
40         //step1;n!<=phi[p]
41         for(;n<=m&&fac<phi[p];n++,fac*=n)
42             if(pow(n,fac)==b)ans++;
43         //step2:n!%phi[p]!=0
44         fac%=phi[p];
45         for(;n<=m&&fac;n++,fac=fac*n%phi[p])
46             if(pow(n,fac+phi[p])==b)ans++;
47         //step3:n!%phi[p]==0
48         if(n<=m){
49             ULL rel=m-n+1;
50             for(ULL i=0;i<p;i++){
51                 mod[i]=pow(n+i,phi[p]);
52                 tot+=(mod[i]==b?1:0);
53             }
54             ans+=(ULL)tot*(rel/p);
55             rel%=p;
56             for(ULL i=0;i<rel;i++){
57                 ans+=(mod[i]==b?1:0);
58             }
59         }
60         printf("Case #%d: %I64u\n",ca,ans);
61     }
62 }
原文地址:https://www.cnblogs.com/swm8023/p/2661267.html