【BZOJ 2219】【超详细题解】数论之神
来源:互联网 发布:拼图游戏源码 编辑:程序博客网 时间:2024/04/29 19:46
2219: 数论之神
Time Limit: 3 Sec Memory Limit: 259 MB
Submit: 365 Solved: 33
[Submit][Status][Discuss]
Description
在ACM_DIY群中,有一位叫做“傻崽”的同学由于在数论方面造诣很高,被称为数轮之神!对于任何数论问题,他都能瞬间秒杀!一天他在群里面问了一个神题: 对于给定的3个非负整数 A,B,K 求出满足 (1) X^A = B(mod 2*K + 1) (2) X 在范围[0, 2K] 内的X的个数!自然数论之神是可以瞬间秒杀此题的,那么你呢?
Input
第一行有一个正整数T,表示接下来的数据的组数( T <= 1000) 之后对于每组数据,给出了3个整数A,B,K (1 <= A, B <= 10^9, 1 <= K <= 5 * 10^8)
Output
输出一行,表示答案
Sample Input
3
213 46290770 80175784
3 46290770 80175784
3333 46290770 80175784
Sample Output
27
27
297
HINT
新加数组一组–2015.02.27
Source
数论 鸣谢 AekdyCoin
中国剩余定理+阶+原根+指标+扩展欧几里得~
首先说说概念:
1.【阶】
满足
记作
2.【原根】
若
(1)只有
(2)
(证明见这里)
(3)
(这也是原根的求法)
3.【指标】
若
记作
(1)
(2)
(3)
(4)指标的求法:
先求出
(BSGS详见这里)
接下来说这道题。。
求方程xA≡B(modP) 的解的个数。
设
为什么呢?
对于每一个
可以求出
设原方程的解为
于是形成了
那么一共有
于是问题变成了求xA≡B(modpa) 的解的个数。
分三种情况讨论:
1.(pa,B)=B
此时原方程变成了
设
那么最小的
此方程的解的个数为
2.(pa,B)>1
设
(1)如果
(2)否则把方程转化为
由于此时
在原式中
可是在后一个式子中
因此我们需要在结果之后乘上
3.(pa,B)=1
此时的方程是
我们利用前面说的指标的性质可以将此方程转化为
利用BSGS求出
原方程解的个数对应上面那个方程的解的个数!!
(1)如果
(2)否则解的个数为
吼吼,第一次用Mathjax和markdown写博客~
#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>#include <cmath>#include <cstdlib>#define inf 1e17#define LL long long#include <map>using namespace std;map<LL,LL> mp;struct data{ LL p,c,pc;}a[100005];int num,cnt;LL f[100005];void Chai(int x){ num=0; for (int i=2;i<sqrt(x+0.5);i++) if (x%i==0) { a[++num].p=i; a[num].c=0,a[num].pc=1; while (x%i==0) x/=i,a[num].c++,a[num].pc*=i; if (x==1) break; } if (x!=1) a[++num].p=x,a[num].pc=x,a[num].c=1;}LL Pow(LL x,LL n,LL mod){ LL ans=1,b=x; while (n) { if (n&1) ans=ans*b%mod; b=b*b%mod; n>>=1LL; } return ans;}LL GetPrimitiveRoot(LL p,LL phi){ int c=0; for (int i=2;i*i<=phi;i++) if (phi%i==0) f[++c]=i,f[++c]=phi/i; for (int g=2;;g++) { int j; for (j=1;j<=c;j++) if (Pow(g,f[j],p)==1) break; if (j==c+1) return g; } return 0;}void exgcd(LL a,LL b,LL &d,LL &x,LL &y){ if (!b) { d=a,x=1,y=0; return; } exgcd(b,a%b,d,y,x); y-=x*(a/b);}LL BSGS(LL A,LL B,LL C){ int m=ceil(sqrt(C+0.5)); mp.clear(); LL now=1; for (int i=1;i<=m;i++) { now=now*A%C; if (!mp[now]) mp[now]=i; } mp[1]=0; A=Pow(A,m,C); now=1LL; for (int i=0;i<=m;i++) { LL d,x,y; exgcd(now,C,d,x,y); x=(x*B%C+C)%C; if (mp.count(x)) return i*m+mp[x]; now=now*A%C; } return 0;}LL Gcd(LL a,LL b){ if (!b) return a; return Gcd(b,a%b);}LL Solve(LL A,LL B,LL k){ LL phi=a[k].pc-a[k].pc/a[k].p,g=GetPrimitiveRoot(a[k].pc,phi); LL ind=BSGS(g,B,a[k].pc); LL ans=Gcd(phi,A); if (ind%ans) return 0; return ans*Pow(a[k].p,cnt-cnt/A,inf);}int main(){ int T; scanf("%d",&T); while (T--) { LL A,B,k; scanf("%lld%lld%lld",&A,&B,&k); LL p=2*k+1; Chai(p); LL ans=1; for (int i=1;i<=num;i++) { if (!ans) break; if (B%a[i].pc==0) ans=ans*Pow(a[i].p,a[i].c-(a[i].c-1)/A-1,inf); else { int b=B; cnt=0; while ((b%a[i].p)==0) b/=a[i].p, a[i].pc/=a[i].p, a[i].c--,cnt++; if (cnt%A) ans=0; else ans=ans*Solve(A,b,i); } } printf("%lld\n",ans); } return 0;}
感悟:
1.WA是因为求原根的地方我没有对
2.分类讨论+原根和指标的应用~
3.UPD:
①a关于p的阶x为什么一定是
假设
②
一定的。
原根与欧拉定理
如果
显然不符合欧拉定理。
③为什么
- 【BZOJ 2219】【超详细题解】数论之神
- BZOJ 2219 数论之神 数论
- bzoj 2219: 数论之神 数论
- bzoj-2219 数论之神
- 【BZOJ】【P4407】【于神之怒加强版】【题解】【数论】
- bzoj 2219: 数论之神 (BSGS+GCD+数论)
- BZOJ 2219 数论之神 BSGS+CRT
- 【BZOJ】【P2818】【Gcd】【数论】【题解】
- [阶 原根 指标]BZOJ 2219 数论之神
- [BZOJ]2219 数论之神 离散对数 + 原根
- [BZOJ 1101] POI 2007 Zap · 莫比乌斯 & 分块 超详细题解
- 【BZOJ】【P1965】【AHOI2005】【SHUFFLE 洗牌】【题解】【数论】
- 【BZOJ】【P1406】【AHOI2007】【密码箱】【题解】【数论】
- 【BZOJ】【P2986】【Non-Squarefree Numbers】【题解】【数论】
- NOIP2011 计算系数 题解(超详细)
- NOIP2011 观光公交 题解(超详细)
- BZOJ 2142 礼物 神TM数论之最终版
- 【BZOJ】【P1951】【Sdoi2010】【古代猪文】【题解】【数论】
- Java方法参数传递(Java swap函数)
- 资源列表
- 在vs2010上配置opencv的环境
- 顺序栈10种操作的实现
- Sublime Text 3 Windows下简单安装配置
- 【BZOJ 2219】【超详细题解】数论之神
- Subsets II
- 提升Web性能的8个技巧总结
- 方法的重载(overload)和覆盖(override)
- JQuery实现笼罩层
- 如何使用Docker进行Java入门级开发
- js中indexof
- seajs+easyui实战
- Android性能优化典范