博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj2219: 数论之神
阅读量:4602 次
发布时间:2019-06-09

本文共 3070 字,大约阅读时间需要 10 分钟。

1 #include 
2 #include
3 #include
4 #include
5 #include
6 using namespace std; 7 typedef long long int64; 8 int ca,top,prim[50005]; 9 int64 A,B,K,pi,pk,ans,ti,q; 10 int64 ksm(int64 x,int64 y){ 11 if (y==0) return 1; 12 if (y==1) return x; 13 int64 d=ksm(x,y/2); 14 if (y%2==1) return d*d*x; 15 else return d*d; 16 } 17 int64 exgcd(int64 a,int64 b,int64 &x,int64 &y){ 18 if (b==0){ 19 x=1,y=0; 20 return a; 21 } 22 int64 temp=exgcd(b,a%b,x,y),tmp; 23 tmp=x,x=y,y=tmp-a/b*y; 24 return temp; 25 } 26 int64 YuanGen(int64 x){ 27 bool flag; 28 top=0; 29 int64 temp=x-1; 30 for (int i=2;i<=sqrt(x-1);i++){ 31 if (temp%i==0){ 32 prim[++top]=i; 33 while (temp%i==0) temp/=i; 34 } 35 } 36 if (temp>1) prim[++top]=temp; 37 for (int i=1;;i++){ 38 flag=1; 39 for (int j=1;j<=top;j++){ 40 if (ksm(i,(x-1)/prim[j])%x==1){ 41 flag=0; 42 break; 43 } 44 } 45 if (flag) return i; 46 } 47 } 48 #define maxn 100005 49 #define maxm 400005 50 int now[maxn],prep[maxm]; 51 int64 val[maxm]; 52 void insert(int x,int64 y){ 53 int64 pos=y%maxn; 54 prep[x]=now[pos],now[pos]=x,val[x]=y; 55 } 56 int find(int64 x){ 57 int64 pos=x%maxn; int ans=maxm*4; 58 for (int i=now[pos];i!=-1;i=prep[i]){ 59 if (val[i]==x) ans=min(ans,i); 60 } 61 if (ans==maxm*4) return -1; 62 else return ans; 63 } 64 int64 BSGS(int64 A,int64 B,int64 C){ 65 memset(now,-1,sizeof(now)); 66 int64 pos,temp=ceil(sqrt(C*1.0)),D=1,R=1; 67 for (int i=0;i
1){124 pi=pk=temp; ti=1;125 ans*=work(A,B);126 }127 printf("%lld\n",ans);128 }129 return 0;130 }
View Code

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2219

题目大意:在ACM_DIY群中,有一位叫做“傻崽”的同学由于在数论方面造诣很高,被称为数轮之神!对于任何数论问题,他都能瞬间秒杀!一天他在群里面问了一个神题: 对于给定的3个非负整数 A,B,K 求出满足 (1) X^A = B(mod 2*K + 1) (2) X 在范围[0, 2K] 内的X的个数!自然数论之神是可以瞬间秒杀此题的,那么你呢?

第一行有一个正整数T,表示接下来的数据的组数( T <= 1000) 之后对于每组数据,给出了3个整数A,B,K (1 <= A, B <= 10^9, 1 <= K <= 5 * 10^8)

输出一行,表示答案。

做法:这题很像之前写过的一个题,用原根+指标+bsgs即可,但是那一题B,C互质,且C一定存在原根。这题不一样了,设C=2*k+1,C不一定存在原根,但是我们可以将其标准分解,这些pi^ti一定存在原根,因为C%2==1,一定不会有2的幂,而奇素数的a次幂,a>=1,一定存在原根。我们对每个x^A=B(mod pi^ti)(0=<x<pi^ti)求出解的个数后乘起来就是原来的解,至于为什么,右转百度搜中国剩余定理推论。

怎么求x^A=B(mod pi^ti)(0=<x<pi^ti)的解的个数呢?我们将B%pi^ti,为了一些边界情况,我们要分情况讨论,当B=0时,那么x^A一定是pi^ti的倍数,我们x中存在因子p^a,且a*A>=ti,那么只要是p^a的倍数就行,可以手推式子。

当B>0时,我们将B分解为pi^b  * T,我们要想办法把pi^b约去,那么x^A中也要刚好有pi^b次方,否则之后同余不成立,所以当A不整除b时无解,令k=b/A,那么x=p^k  * G,G属于[0,p^(ti-k)),约去后化简为G^A = T (mod pi^(ti-b)),G属于[0,pi^(ti-b)),mod数存在原根,T与mod数互质,转化为了弱化版,可以用bsgs+原根求解,设解数为ans,最后应该ans*=p^(b-k),因为定义域缩小了,且存在大小为p^(ti-b)的循环节,除一下就知道最后要扩大的倍数了。

 

那么怎么求x^A=B(mod C)呢?  C存在原根,且(B,C)=1。我们找到C的原根g,找到B在原根g下modC的指标,x也必定为原根g的若干次方%C,式子变为

g^(aA)=g^b(mod C),由于循环节phi(C),变为aA=b(mod phi(C)),0=<a<phi(C),用扩展欧几里得算法即可实现。

转载于:https://www.cnblogs.com/OYzx/p/5773409.html

你可能感兴趣的文章
良好的编程规范
查看>>
struts2 入门
查看>>
.net 编译原理
查看>>
mean 快速开发和现有技术的对比分析
查看>>
Metro Style app :浏览器扩展
查看>>
linux的kernel是怎样工作的(TI_DM36X_ARM系统)(1)
查看>>
[luogu4310] 绝世好题 (递推)
查看>>
[luogu3203 HNOI2010] 弹飞绵羊 (分块)
查看>>
-Dmaven.multiModuleProjectDirectory system propery is not set.
查看>>
Python2 unichr() 函数
查看>>
Python 字典 copy()方法
查看>>
Minimum Path Sum
查看>>
Remove Duplicates from Sorted Array II
查看>>
常量指针和指针常量巧妙记忆方法[转]
查看>>
python-haproxy作业讲解视频总结
查看>>
批处理文件脚本总结
查看>>
快速排序C++代码
查看>>
mui搜索框 搜索点击事件
查看>>
bzoj 5289: [Hnoi2018]排列
查看>>
joomla处境堪忧
查看>>