首先這破題很容易懂的叭,分析過程我真的懶得寫,然後看代碼唄
- 首先這道題的擴展歐幾里得寫的挺簡潔的,以後就這麼寫了
- 數論一般會牽扯到一些比如枚舉啊之類的,注意一下,就像那種打表之類的題目,有的要先判斷特殊情況,恰好的時候,判斷一下是否符合題意,然後過渡到一般情況,就是數學歸納法的思想,至於說爲什麼會用到這種,因爲這個題目很明顯是遞推。
- 判斷是k或者k-1的話自己慢慢體會叭,反正能看懂,至於代碼中爲啥k1=n,因爲最後一行都是可以k中顏色的
- 分析過程見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,沒提示錯誤,但是一般情況的答案就數值很奇怪,錯了一段時間。