首先这破题很容易懂的叭,分析过程我真的懒得写,然后看代码呗
- 首先这道题的扩展欧几里得写的挺简洁的,以后就这么写了
- 数论一般会牵扯到一些比如枚举啊之类的,注意一下,就像那种打表之类的题目,有的要先判断特殊情况,恰好的时候,判断一下是否符合题意,然后过渡到一般情况,就是数学归纳法的思想,至于说为什么会用到这种,因为这个题目很明显是递推。
- 判断是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,没提示错误,但是一般情况的答案就数值很奇怪,错了一段时间。