【链+环结构】

【链+环结构】

有时题目造样例打表迭代完 会得到链+环的结构

单独算
统一算
最后环断链单独算

幂中幂plus

https://ac.nowcoder.com/acm/contest/113313/F
注意这题代码的简洁程度

思路

打表可以发现规律是一个链+环
直接模拟即可
注意快速幂不要爆ll了

代码

i64 base,c0,mod;
i64 qmi(i64 a,i64 k,i64 p){
    a%=p;
	i64 res=1LL;
	while(k){
		if(k&1LL) res=res*a%p;
		k>>=1LL;//删去k的末位 
		a=a*a%p;
	}
	return res;
}
void solve(){
    cin>>base>>c0>>mod;
    int q;
    if(mod==1){
        cin>>q;
        while(q--){
            i64 k;
            cin>>k;
            cout<<0<<endl;
        }
        return;
    }
    vector<i64> biao(mod+1,-1);
    i64 res=qmi(base,c0,mod);
    int cnt=0;//编号
    vector<i64> pre(1,0);
    while(biao[res]==-1){
        cnt++;
        biao[res]=cnt;
        pre.push_back((pre.back()+res)%mod);
        res=qmi(base,res,mod);
    }
    i64 len=cnt-biao[res]+1;//环长度
    i64 sum=(pre[cnt]-pre[biao[res]-1]+mod)%mod;
    cin>>q;
    while(q--){
        i64 k;
        i64 ans=0;
        cin>>k;
        if(k<=cnt){
            ans=pre[k]%mod;
        }
        else{
            //加环
            i64 t=(k-biao[res]+1)/len%mod;
            ans=t*sum%mod;
            //加链
            ans=(ans+pre[biao[res]-1])%mod;
            //加环额外
            i64 r=(k-(biao[res]-1))%len;
            ans=(ans+pre[biao[res]-1+r]-pre[biao[res]-1]+mod)%mod;
        }
        cout<<ans<<endl;
    }
}

Ping Pong

https://ac.nowcoder.com/acm/contest/108306/L

题目大意

2c062606-b309-422d-b7b2-6fb7cea57e6e

思路

34e7b074-e1d1-4904-936e-e09d188cf27d

代码

const int N=3e5+10;
int n,k;
//最强者打n-1轮后必输,后续循环节长度为(2*n-2)
void solve(){
    cin>>n>>k;
    //找一定次数一定能找出环
    int lun=min(4*n,k);
    vector<int> a(n+1,0),cnt(n+1,0);
    int mx=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        mx=max(mx,a[i]);
    }
    queue<int> q;
    int now=1,tot=0;
    for(int i=2;i<=n;i++) q.push(i);
    while(lun--){
        k--;
        int x=q.front();
        q.pop();
        cnt[x]++;cnt[now]++;
        tot++;
        if(a[now]<a[x] || tot==n){
            q.push(now);
            now=x;
            tot=1;//注意这里算对方赢,所以tot从1开始计数!
        }
        else q.push(x);
    }
    //再次模拟到循环节:mx为队首 否则就是循环完了
    while(k){
        int x=q.front();
        if(a[x]==mx) break;
        k--;
        q.pop();
        cnt[x]++;cnt[now]++;
        tot++;
        if(a[now]<a[x] || tot==n){
            q.push(now);
            now=x;
            tot=1;//注意这里算对方赢,所以tot从1开始计数!
        }
        else q.push(x);
    }
    int round=k/(2*n-2);
    k-=(2*n-2)*round;
    for(int i=1;i<=n;i++){
        if(i!=now && i!=q.front()) cnt[i]+=2*round;
        else cnt[i]+=n*round;
    }
    while(k--){
        int x=q.front();
        q.pop();
        cnt[x]++;cnt[now]++;
        tot++;
        if(a[now]<a[x] || tot==n){
            q.push(now);
            now=x;
            tot=1;//注意这里算对方赢,所以tot从1开始计数!
        }
        else q.push(x);
    }
    for(int i=1;i<=n;i++){
        cout<<cnt[i]<<" ";
    }
    cout<<endl;
}
posted @ 2025-08-12 21:58  White_ink  阅读(8)  评论(0)    收藏  举报