Emoogle Grid

首先这破题很容易懂的叭,分析过程我真的懒得写,然后看代码呗

  1. 首先这道题的扩展欧几里得写的挺简洁的,以后就这么写了
  2. 数论一般会牵扯到一些比如枚举啊之类的,注意一下,就像那种打表之类的题目,有的要先判断特殊情况,恰好的时候,判断一下是否符合题意,然后过渡到一般情况,就是数学归纳法的思想,至于说为什么会用到这种,因为这个题目很明显是递推。
  3. 判断是k或者k-1的话自己慢慢体会叭,反正能看懂,至于代码中为啥k1=n,因为最后一行都是可以k中颜色的
  4. 分析过程见https://blog.csdn.net/qingqiu_wd/article/details/75676133
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>/////
#include<cmath>
using namespace std;
#define ll long long
ll n;ll k;ll r;
int f=1;
const int modn=1e8+7;ll b; 
struct node{
	ll x,y;
}nod[505];
bool cmp(node a,node b){
	if(a.y==b.y) return a.x<b.x;
return a.y<b.y;
}
ll mod_pow(ll a,ll b){
	ll res=1;
	while(b){
		if(b&1){
			res=(res*a)%modn;
		} 
		a=(a*a)%modn;
		b>>=1;
	}
	return res%modn;
} 
void exgcd(ll a,ll b,ll &x,ll &y){
	if(b!=0){
		 exgcd(b,a%b,y,x);
		y-=(a/b)*x;
	}
	else {
		x=1; y=0; return;
	}
}
ll inv(ll p){
	ll x,y;
	exgcd(p,modn,x,y);
	return (x%modn+modn)%modn;
}
ll log_pow(ll a,ll b){
	ll m=(ll)sqrt(modn+0.5);//
	
	map<ll,ll> q;//两个long long 
	q[1]=0;//初始化 
	ll ans=1;
	for(ll i=1;i<=m;i++){
		ans=(ans*a)%modn;
		if(!q.count(ans)) q[ans]=i;
	}
	ll pm=inv(mod_pow(a,m));
	for(ll i=0;i<m;i++){
		if(q.count(b)) return (i*m+q[b])%modn;
		b=b*pm%modn;	//折半了 
	}
	 
} 
void solve(){
	ll lm=1;
	for(ll i=0;i<b;i++){
		scanf("%lld%lld",&nod[i].x,&nod[i].y);
		if(lm<nod[i].x) lm=nod[i].x;
	}
	printf("Case %d: ",f++);
	sort(nod,nod+b,cmp);
	ll ans=1;
	ll k1=n;//本来就有n 个 
	/*for(int i=0;i<b;i++){
		if(nod[i].x==1){
			k1--;
		}
		else if(nod[i].x!=lm&&i+1<=lm){
			k1++;
		}
		else {
			
		}
	}*/
	for(ll i = 0;i < b;i++){
        if(nod[i].x==1) k1--;
        if(nod[i].x!=lm){
            if(i+1<b&&nod[i+1].y==nod[i].y){//
                if(nod[i].x+1!=nod[i+1].x){
                    k1++;
                }
            }
            else k1++;//
        }
    }
	ans=ans*mod_pow(k,k1)%modn;
	ans=ans*mod_pow(k-1,n*lm-k1-b)%modn; 
	if(ans==r){
		printf("%lld\n",lm);
		return;
	}
	k1=0;
	for(ll i=0;i<b;i++){
		if(nod[i].x==lm){
			k1++;
		}
	}//特殊 
	ans=ans*mod_pow(k,k1)%modn;
	ans=ans*mod_pow(k-1,n-k1)%modn;
//	cout<<ans<<"ans2"<<endl;
	if(ans==r){
		printf("%lld\n",lm+1);
		return;
	}

	r*=inv(ans);
	//cout<<inv(ans)<<"w"<<endl;
	r=r%modn;
	k=mod_pow(k-1,n);//
//	cout<<k<<" f"<<r<<endl;
	printf("%lld\n",(log_pow(k,r)+lm+1)%modn);
	return ;
}
int main(){
	ll t;
	scanf("%lld",&t);
	while(t--){
		//ll n,k,r;
	//	ll b;//全局变量混乱 
		scanf("%lld%lld%lld%lld",&n,&k,&b,&r);
		 solve();
	}
	return 0;
}

那个扩展欧几里得本身是void 型,结果多写了个return,没提示错误,但是一般情况的答案就数值很奇怪,错了一段时间。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章