BZOJ3884 上帝与集合的正确用法(欧拉函数)
2015-06-02 10:00
447 查看
【题解】
函数y = 2^x mod p 当p是奇数时,由于 2^φ(p) mod p = 1 ,所以函数会出现循环节长度为φ(p)的循环*(不一定是最小循环)
当p是偶数时,设 p = 2^k * q,q为奇数,函数会出现循环节长度为φ(q)的循环
所以有:
( 2^2^2…^2 ) mod p = [ 2^(2^2…^2-k) *2^k ] mod (2^k*q) ,q为奇数
= 2^k * [ 2^(2^2…^2-k) mod q ]
= 2^k * [ 2^[(2^2…^2-k)modφ(q)] mod q ]
= 2^k * [ 2^[ ( 2^2…^2 modφ(q) - k modφ(q) ) modφ(q) ] mod q ]
其中,( 2^2…^2 ) modφ(q) 与 ( 2^2^2…^2 ) mod p 形式相同,且φ(q)<p,即模数在不断减小,直到1或2^k为止,因此可以递归求出答案
【代码】
函数y = 2^x mod p 当p是奇数时,由于 2^φ(p) mod p = 1 ,所以函数会出现循环节长度为φ(p)的循环*(不一定是最小循环)
当p是偶数时,设 p = 2^k * q,q为奇数,函数会出现循环节长度为φ(q)的循环
所以有:
( 2^2^2…^2 ) mod p = [ 2^(2^2…^2-k) *2^k ] mod (2^k*q) ,q为奇数
= 2^k * [ 2^(2^2…^2-k) mod q ]
= 2^k * [ 2^[(2^2…^2-k)modφ(q)] mod q ]
= 2^k * [ 2^[ ( 2^2…^2 modφ(q) - k modφ(q) ) modφ(q) ] mod q ]
其中,( 2^2…^2 ) modφ(q) 与 ( 2^2^2…^2 ) mod p 形式相同,且φ(q)<p,即模数在不断减小,直到1或2^k为止,因此可以递归求出答案
【代码】
#include<stdio.h> #include<stdlib.h> typedef long long LL; int er[35]={0}; int phi(int n) { int i,ans=n; for(i=2;i*i<=n;i++) { if(n%i==0) ans=ans/i*(i-1); while(n%i==0) n/=i; } if(n>1) ans=ans/n*(n-1); return ans; } LL ksm(int n,LL mod) { LL ans; if(n==0) return 1; if(n==1) return 2; ans=ksm(n/2,mod); ans=ans*ans; if(n%2==1) ans*=2; return ans%mod; } int dfs(int p) { int k,t; for(k=0;p%2==0;p/=2) k++; if(p==1) return 0; t=phi(p); return er[k]*(int)ksm( (dfs(t)-k%t+t)%t , (LL)p ); } int main() { int T,p,i; er[0]=1; for(i=1;i<=30;i++) er[i]=2*er[i-1]; scanf("%d",&T); for(;T>0;T--) { scanf("%d",&p); printf("%d\n",dfs(p)); } return 0; }
相关文章推荐
- Oracle 死锁的检测查询及处理
- https 方式使用git@osc设置密码的方式
- NYOJ 28 大数阶乘
- mysql一: 索引优化
- 疯狂Java学习笔记(68)-----------synchronized
- 【原创】kafka server源代码分析(二)
- MySQL查询长数据是无值返回(可以尝试换行符)
- C#获取本执行程序所在的当前路径
- IPO\IPOH快速开关机相关
- android 详细解答json解析与生成 JSONObject JSONArray
- 利用CK11N改标准价格需要注意的地方
- git config命令使用
- dialog
- Flex4之皮肤定制【Skin类和Skin类】
- 深入浅出OOP(六): 理解C#的Enums
- 凌小宁教授
- Oracle EBS R12.2 修改APPS密码方法
- GIT在Linux上的安装和使用简介
- label的for属性
- NPOI的版本查看