题意,给定一个素数p(2<p>2000),要求1<=x<p,x-1,x^2-1,..x^(p-2)-1都不能被p整除,但x^(p-1)-1能整除p,要统计这样的x有多少个
思路,由于此题p值比较小,于是我是用快速幂取模(经典分治算法),直接计算幂,看是不是满足条件
#include<iostream> #include<algorithm> #include<list> #include<cstdio> #include<stack> #include<string> #include<cstring> #define MAXN 100005 #define debug_cout(x,y) cout<<x<<":"<<y<<endl using namespace std; long exp_mod(long a,long n,long b) { long long t; if(n==0) return 1%b; if(n==1) return a%b; t=exp_mod(a,n/2,b); t=t*t%b; if((n&1)==1) t=t*a%b; return t; } int main(){ int p; cin>>p; int x,i,flag,ans=0; for(x=1;x<p;x++){ flag =1; for (i=1;i<p-1;i++) { int t = exp_mod(x,i,p); t = (t+p-1) % p; if (t==0) { flag = 0;break; } } if (flag==1 && ((exp_mod(x,p-1,p)+p-1)%p)==0) ans++; } cout<<ans; return 0; }
算法复杂度为O(P^2*logP)
后面发现,完全没必要每个p都快速幂算一次,不需要快速幂求模,因为x的1~p-1次幂模p可以直接一个for迭代计算出来,算法复杂度O(P^2)
看了tutorial这道题还有O(sqrt(P))的解法,没想明白为什么
大概意思
费马小定理是数论中的一个重要定理,其内容为: 假如p是质数,且(a,p)=1,那么
a^(p-1) ≡1(mod p) 假如p是质数,且a,p互质,那么 a的(p-1)次方除以p的余数恒等于1
对于这道题只要找到与p-1互质的数的个数,就能满足那两个条件,而找与p-1互质数的个数可以用欧拉函数(先求整除p-1的质因子,再带入公式