ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P4195 【模板】扩展BSGS

2021-06-19 11:57:27  阅读:166  来源: 互联网

标签:return Gcd hask long tot P4195 include 模板 BSGS


题目

题目

思路

先把exBSGS变成普通BSGS。
我们这样做:
a x ≡ b (   m o d     c ) = > a x + c y = b a^x\equiv b(\bmod~c)=>a^x+cy=b ax≡b(mod c)=>ax+cy=b
接下来我们不停地除a,c的最大公约数(d1)。
b 1 = a d 1 a x − 1 + c 1 y b_1={a\over d_1}a^{x-1}+c_1y b1​=d1​a​ax−1+c1​y
我们接下来接着除gcd(a,c1)=d2
b 2 = a 2 d 1 d 2 a x − 2 + c 2 y b_2={a^2\over d_1d_2}a^{x-2}+c_2y b2​=d1​d2​a2​ax−2+c2​y
我们不难发现此时若b不被gcd整除,则无解。
设一共做了 n n n次, D = a n d 1 d 2 … … d n D={a^n\over d_1d_2……d_n} D=d1​d2​……dn​an​
剩下的 a x − n ≡ b n ⋅ D − 1 (   m o d     c n ) a^{x-n}\equiv b_n·D^{-1}(\bmod~c_n) ax−n≡bn​⋅D−1(mod cn​)普通BSGS可解。


接下来考虑普通BSGS。
由指数模的周期性,得若有解,必有c以内的解。
我们考虑优(bi)美(tai)的分块。
分 n \sqrt n n ​块,那么每块就是 m = n m=\sqrt n m=n ​个数。
那么这时原式变成
a i m − j ≡ b (   m o d     c ) = > a i m ≡ a j b (   m o d     c ) a^{im-j}\equiv b(\bmod~c)=>a^{im}\equiv a^jb(\bmod~c) aim−j≡b(mod c)=>aim≡ajb(mod c)
这里我们需要枚举 1 < = i < = c , 0 < = j < = c 1<=i<=\sqrt c,0<=j<=\sqrt c 1<=i<=c ​,0<=j<=c
我们把右式存入hash表里(也可以map,只要数据水),这里一共 O ( n ) O(\sqrt n) O(n ​)。
然后再枚举i,又 O ( n ) O(\sqrt n) O(n ​)。
code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<cmath>
#include<queue>
#include<deque>
using namespace std;
//When I wrote this code,God and I unterstood what was I doing 
long long gcd(long long a,long long b)
{
	long long r=a%b;
	while (r)
	{
		a=b,b=r,r=a%b;
	}
	return b;
}
long long exgcd(long long a,long long b,long long &x,long long &y)
{
	if (b==0)
	{
		x=1,y=0;
		return a;
	}
	long long r=exgcd(b,a%b,y,x);
	y-=(long long)(a/b)*x;
	return r;
}
long long inv(long long a,long long m)
{
	long long x,y;
	exgcd(a,m,x,y);
	return (x%m+m)%m;
}
struct fP{
	long long tot,head[(((1<<16)-1)<<2)],nxt[500005],b[500005],v[500005],top,sck[500005];
	void init()
	{
		tot=0;
		while (top) head[sck[top--]]=0;
		return;
	}
	void insert(long long x,long long y)
	{
		long long hask=x%(((1<<16)-1)<<2);
		for (long long i=head[hask];i;i=nxt[i])
		{
			if (b[i]==x)
			{
				v[i]=y;
				return;
			}
		}
		if (!head[hask]) sck[++top]=hask;
		nxt[++tot]=head[hask],head[hask]=tot;
		b[tot]=x,v[tot]=y;
		return;
	}
	long long QuantAsk(long long x)
	{
		long long hask=x%(((1<<16)-1)<<2);
		for (long long i=head[hask];i;i=nxt[i])
		{
			if (b[i]==x) return v[i];
		}
		return -1;
	}
} kyx;
long long BSGS(long long a,long long b,long long c)
{
	if (b==1||c==1) return 0;
	long long cnt=0,Gcd=gcd(a,c),d=1;
	while (Gcd!=1)
	{
		if (b%Gcd!=0) return -1;
		cnt++,b/=Gcd,c/=Gcd;
		d=d*(a/Gcd)%c;
		Gcd=gcd(a,c);
	}
	b=b*inv(d,c)%c;
	kyx.init();
	long long block=ceil(sqrt(c)),p=1;
	for (long long i=0;i<block;i++)
	{
		if (p==b) return i+cnt;
		kyx.insert(p*b%c,i);
		p=p*a%c;
	}
	long long q=p,t;
	for (long long i=block;i-block+1<=c-1;i+=block)
	{
		t=kyx.QuantAsk(q);
		if (t!=-1) return i-t+cnt;
		q=q*p%c;
	}
	return -1;
}
int main()
{
	long long a,b,c;
	while (1)
	{
		scanf("%lld%lld%lld",&a,&b,&c);
		if (a==0&&b==0&&c==0) return 0;
		a%=b,c%=b;
		//if (check(a,b,c)) continue;
		long long wj=BSGS(a,c,b);
		if (wj==-1) puts("No Solution");
		else printf("%lld\n",wj);
	}
	return 0;
}
//Now,only God know
//但行好事,莫问前程 

标签:return,Gcd,hask,long,tot,P4195,include,模板,BSGS
来源: https://blog.csdn.net/weixin_49843717/article/details/118050927

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有