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,沒提示錯誤,但是一般情況的答案就數值很奇怪,錯了一段時間。

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