bzoj 2219: 数论之神 (BSGS+GCD+数论)
来源:互联网 发布:2017永久免费顶级域名 编辑:程序博客网 时间:2024/04/30 02:54
题目描述
传送门
题目大意:
求
题解
这道题用到的数论知识好多啊,还是一点点从头顺吧。
首先将
根据中国剩余定理的推论,模
然后我们对于
(1)
我们只要找到最小的a,那么
所以解的个数就是
(2)
所有奇素数以及他们的幂都有原根。
我们求出
那么如何求原根呢?
原根:如果g是P的原根,那么g的
根据欧拉定理
那么我们是否需要将
一般原根的大小不会太大,所有我直接暴力枚举判断即可。
求出原根后,我们就得到了方程
上面方程的解的个数就是原式的解的个数。
形如
令
如何证明?扩展欧几里得定理,要求
设
那么
那么x其实可以表示成
(3)
虽然B是
令
那么方程可以写成
其中A|a,否则无解。因为如果A不是a的因数,那么
所以可以设
那么方程就变成了
那么方程解的数量是否等于方程
其实是不对的,因为我们在化简的时候定义域的范围改变了,x的取值范围是
第二个方程的求解方式同情况(2)
代码
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<map>#define LL long long#define N 100003 using namespace std;map<LL,int> mp;int pd[N],prime[N],n,f[N];LL m[N],cnt[N];void init(int n){ for (int i=2;i<=n;i++) { if (!pd[i]) prime[++prime[0]]=i; for (int j=1;j<=prime[0];j++){ if (prime[j]*i>n) break; pd[prime[j]*i]=1; if (i%prime[j]==0) break; } }}LL gcd(LL x,LL y){ LL r; while (y) { r=x%y; x=y; y=r; } return x;}LL get_phi(LL x){ LL ans=x; for (int i=2;i*i<=x;i++) if (x%i==0) { ans=(LL)ans/i*(i-1); while (x%i==0) x/=i; } if (x>1) ans=ans/x*(x-1); return ans;}LL quickpow(LL num,int x){ LL base=num; LL ans=1; while (x) { if (x&1) ans=ans*base; x>>=1; base=base*base; } return ans;}LL quickpow(LL num,int x,LL p){ LL base=num%p; LL ans=1; while (x) { if (x&1) ans=ans*base%p; x>>=1; base=base*base%p; } return ans;}LL calc(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 (quickpow(g,f[j],p)==1) break; if (j==c+1) return g; } return 0;}LL bsgs(LL a,LL b,LL p) { LL m=ceil(sqrt(p)); LL ans=b; LL d=1; mp.clear(); LL tmp=quickpow(a,m,p); mp[ans]=0; for (LL i=1;i<=m;i++) ans=ans*a%p,mp[ans]=i; for (int LL i=1;i<=m+1;i++) { d=d*tmp%p; if (mp[d]) { return (LL)i*m-mp[d]; } } return -1; } LL solve(LL A,LL B,LL P,LL k){ LL p=quickpow(P,k); if (B%p==0) { LL a=(k-1)/A+1; return quickpow(P,k-a); } LL t=0; LL opt=1; LL X=B; while (B%P==0) B/=P,t++; if (t%A) return 0; if (gcd(X,p)!=1) { p=quickpow(P,k-t); opt=quickpow(P,t-t/A); } LL phi=get_phi(p); LL g=calc(p,phi); LL C=bsgs(g,B,p); if (C==-1) return 0; t=gcd(A,phi); if (C%t==0) return (LL)t*opt; else return 0;}int main(){ freopen("a.in","r",stdin); freopen("my.out","w",stdout); int T; scanf("%d",&T); init(100000); while (T--) { LL A,B,K; scanf("%lld%lld%lld",&A,&B,&K); LL p=2*K+1; n=0; for (int i=1;prime[i]*prime[i]<=p;i++) if (p%prime[i]==0) { m[++n]=prime[i]; cnt[n]=0; while (p%prime[i]==0) p/=prime[i],cnt[n]++; } if (p>1) m[++n]=p,cnt[n]=1; LL ans=1; for (int i=1;i<=n;i++) ans=ans*solve(A,B,m[i],cnt[i]); printf("%lld\n",ans); }}
阅读全文
0 0
- bzoj 2219: 数论之神 (BSGS+GCD+数论)
- BZOJ 2219 数论之神 BSGS+CRT
- BZOJ 2219 数论之神 数论
- bzoj 2219: 数论之神 数论
- bzoj-2219 数论之神
- bsgs(数论)
- BZOJ 2818 Gcd (数论 欧拉)
- 【BZOJ】【P2818】【Gcd】【数论】【题解】
- [HDU2588]GCD(数论)
- 数论 BSGS 模板
- BZOJ-2242 计算器 快速幂+拓展欧几里得+BSGS(数论三合一)
- POJ 2417/BZOJ 3239(Discrete Logging-BSGS)[Template:数论]
- BZOJ 3505 数三角形 (数论 组合数 gcd)
- 【BZOJ 2219】【超详细题解】数论之神
- [阶 原根 指标]BZOJ 2219 数论之神
- [BZOJ]2219 数论之神 离散对数 + 原根
- 数论、、gcd
- 数论+gcd
- sony apkanalyser使用
- java Web开发_购物车功能实现
- go"???
- Java实现-最大间距
- Unity3D 03-代码及效率优化总结
- bzoj 2219: 数论之神 (BSGS+GCD+数论)
- 查看虚拟机里的Centos7的IP
- 一种非递归实现广度优先搜索(BFS)的方法
- PowerDesigner的Name和Code不同步设置
- MYSQL—— TIME_TO_SEC函数与UNIX_TIMESTAMP函数区别
- 关于PHP获取QQ授权后的用户信息
- linux设备驱动程序之简单字符设备驱动
- springboot + devtools(热部署)
- 在泛型为Integer的ArrayList中存放一个String类型的对象