UVa11916 - Emoogle Grid

链接

https://uva.onlinejudge.org/external/119/11916.pdf

题解

瞎推一推然后 B S G S BSGS BSGS做一做就行了

代码

#include <bits/stdc++.h>
#define ll long long
#define mod 100000007ll
#define maxn 510
using namespace std;
map<ll,ll> table;
struct block{ll x, y;}bl[maxn];
bool operator<(block a, block b){return a.y==b.y?a.x<b.x:a.y<b.y;}
ll N, M, K, T, R, B;
ll read(ll x=0)
{
	ll c, f=1;
	for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
	for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
	return f*x;
}
void init()
{
	ll i;
	table.clear();
	N=read(), K=read(), B=read(), R=read();
	for(i=1;i<=B;i++)bl[i].x=read(), bl[i].y=read();
	sort(bl+1,bl+B+1);
}
ll fastpow(ll a, ll b, ll c)
{
	ll t=a, ans=1;
	for(;b;b>>=1,t=t*t%c)if(b&1)ans=ans*t%c;
	return ans;
}
ll BSGS(ll A, ll B)
{
	ll k, m=sqrt(mod), b, i, t, Am, Akm, Ab;
	map<ll,ll>::iterator it;
	for(i=0;i<m;i++)
	{
		t=fastpow(A,i,mod);
		it=table.find(t);
		if(it==table.end())table[t]=i;
	}
	Am=fastpow(A,m,mod);
	Akm=1;
	for(k=0;k<=m;k++,Akm=Akm*Am%mod)
	{
		Ab=B*fastpow(Akm,mod-2,mod)%mod;
		it=table.find(Ab);
		if(it!=table.end())return k*m+it->second;
	}
	return -1;
}
ll work()
{
	ll i, j, k, xm=0, now=1, cnt=0;
	if(B==0)
	{
		now=fastpow(K,N,mod);
		if(now==R)return 1;
		return 1+BSGS(fastpow(K-1,N,mod),R*fastpow(now,mod-2,mod)%mod);
	}
	for(i=1;i<=B;i++)xm=max(xm,bl[i].x);
	for(i=1;i<=B;i=j+1)
	{
		cnt++;
		for(j=i;j+1<=B and bl[j+1].y==bl[j].y;j++);
		if(bl[i].x>1)now=now*K%mod*fastpow(K-1,bl[i].x-2,mod)%mod;
		if(bl[j].x<xm)now=now*K%mod*fastpow(K-1,xm-bl[j].x-1,mod)%mod;
		for(k=i+1;k<=j;k++)if(bl[k].x>bl[k-1].x+1)now=now*K%mod*fastpow(K-1,bl[k].x-bl[k-1].x-2,mod)%mod;
	}
	now=now*fastpow(K*fastpow(K-1,xm-1,mod)%mod,N-cnt,mod)%mod;
	if(now==R)return xm;
	for(i=1,cnt=0;i<=B;i++)if(bl[i].x==xm)cnt++;
	now=now*fastpow(K-1,N-cnt,mod)%mod*fastpow(K,cnt,mod)%mod;
	if(now==R)return xm+1;
	return xm+1+BSGS(fastpow(K-1,N,mod),R*fastpow(now,mod-2,mod)%mod);
}
int main()
{
	ll T=read(), kase=1;
	for(kase=1;kase<=T;kase++)
	{
		init();
		printf("Case %lld: %lld\n",kase,work());
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值