【BZOJ2219】数论之神

12 篇文章 0 订阅

反正基本不会做。。数论就是个渣。。

http://blog.csdn.net/popoqqq/article/details/41595187

popoqqq的题解讲的好详细。。

http://blog.csdn.net/lych_cys/article/details/51177928?locationNum=1&fps=1

lych_cys好简练。。。

这题似乎是用个天朝剩余定理将问题变成x^A=B(mod ai^pi)

然后分类讨论。B%(ai^pi)=0时,显然可以直接算

否则,设B=ai^q*b,b<q,然后似乎q%pi=0时才有解(据说很显然),然后原根+指标+bsgs乱搞。。(似乎还是不会的样子。)

#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
using namespace std;
ll A,B,K,ans,c[10000];
map<ll,ll> mp;
ll read()
{
	ll x=1ll;
	char ch;
	while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1ll;
	ll s=ch-48ll;
	while (ch=gc,ch>='0'&&ch<='9') s=s*10ll+ch-48ll;
	return s*x;
}
ll ksm(ll y,ll x)
{
	ll sum=1ll;
	for (ll i=x;i;i>>=1ll,y=(ll)y*y)
		if (i&1ll) sum=(ll)sum*y;
	return sum;
}
ll ksm(ll y,ll x,ll p)
{
	y%=p;
	ll sum=1ll;
	for (ll i=x;i;i>>=1ll,y=(ll)y*y%p)
		if (i&1ll) sum=(ll)sum*y%p;
	return sum;
}
ll gcd(ll x,ll y)
{
	return (y==0)?x:gcd(y,x%y);
}
ll get_g(ll p)//求原根 
{
	ll cnt=0,q=p-1;
	for (ll i=2;i*i<=q;i++)
		if (!(q%i))
		{
			c[++cnt]=i;
			if (i*i!=q) c[++cnt]=q/i;
		}
	for (ll i=2;i<p;i++)
	{
		ll j;
		for (j=1;j<=cnt;j++)
			if (ksm(i,c[j],p)==1) break;
		if (j==cnt+1) return i;
	}
	return 0;
}
ll bsgs(ll y,ll z,ll p)
{
	y%=p;
	mp.clear();
	ll m=ceil(sqrt(p)),now=z;
	for (ll i=0;i<=m;i++,now=now*y%p)
		if (!mp[now]) mp[now]=i;
	ll b=1,d=ksm(y,m,p);
	for (ll i=0;i<=m;i++,b=b*d%p)
		if (mp.count(b)) return (ll)i*m-mp[b];
	return 0;
}
ll solve(ll A,ll B,ll sum,ll a,ll k)//sum=a^k
{
	B%=sum;
	if (!B) return ksm(a,k-((k-1)/A+1));
	ll y=0;
	while (B%a==0) B/=a,y++;
	if (y%A) return 0;//(Gcd)^A=x(mod a^(k-y))
	ll g=get_g(a);
	ll m=sum-sum/a;
	ll Gcd=gcd(A,m);
	if (bsgs(g,B,sum)%Gcd==0) return Gcd*ksm(a,y-y/A);
	return 0;
}
int main()
{
	ll T=read();
	while (T--)
	{
		A=read(),B=read(),K=read();
		ans=1ll,K=K<<1ll|1ll;
		for (ll i=2;i*i<=K;i++)
			if (!(K%i))
			{
				ll now=1ll,j;
				for (j=0;!(K%i);K/=i,now*=i,j++);
				ans=ans*(ll)solve(A,B,now,i,j);
			}
		if (ans&&K>1) ans=(ll)ans*solve(A,B,K,K,1);
		printf("%lld\n",ans);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值