1 条题解

  • 0
    @ 2025-8-24 22:25:37

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Anins
    AFO

    搬运于2025-08-24 22:25:37,当前版本为作者最后更新于2024-09-14 09:23:33,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    [NEERC2015] Generators

    题意

    nn 个序列,对于每个序列给定 x,a,b,cx,a,b,c,并按照 x=(ax+b)modcx=(ax+b) \bmod c 进行扩展,每个序列取一个数进行累加,输出对 kk 取模不为 00 的最大累加和以及每个序列中取出的数的下标,无解输出 1-1

    思路

    1. 显然 ax+bax+b 是单调不减的,那么对 cc 取模就是周期函数,只需求出一个周期即可代表整个序列。

    2. 对每个序列记录对 kk 取模后值不同的最大值和次大值。

    3. 将每个序列最大值累加,若对 kk 取模不为 00,那么输出。

    4. 否则考虑将一个最大值替换成次大值,要求前后差值最小。

    • 若能替换,则替换后对 kk 取模一定不为 00,进行输出。
    • 若不能替换,则意味着无解,输出 1-1

    代码

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    ll n, mod;
    ll x, a, b, c, ans;
    ll vis[10005]; //存储序列元素下标
    struct node {
    	ll index, value; //下标和值 
    }q[10005][2]; //0为最大值,1为次大值 
    void Make_serial() {
    	memset(vis, 0, sizeof(vis));
    	for(int i=1; !vis[x]; i++) {
    		vis[x]=i;
    		x=(a*x+b)%c;
    	}
    }
    void Get_max(ll i) {
    	q[i][0].index=q[i][1].index=q[i][0].value=q[i][1].value=-1;
    	for(int j=c-1; j>=0; j--) {
    		if(!vis[j]) continue;
    		if(j>=q[i][0].value) { //可以更新最大值 
    			if(j%mod!=q[i][0].value%mod) q[i][1]=q[i][0]; //尝试用之前最大值替换次大值 
    			q[i][0].value=j, q[i][0].index=vis[j];
    		} else if(j>q[i][1].value&&j%mod!=q[i][0].value%mod) { //可以更新次大值 
    			q[i][1].value=j, q[i][1].index=vis[j];
    		}
    		if(q[i][0].value!=-1&&q[i][1].value!=-1) break; //最大值和次大值都有了,结束 
    	}
    }
    void Get_ans() {
    	for(int i=1; i<=n; i++) ans+=q[i][0].value; //求最大值累加和 
    	if(ans%mod) { //取模不为0,输出 
    		cout << ans << "\n";
    		for(int i=1; i<=n; i++) cout << q[i][0].index-1 << " ";
    	} else {
    		ll idx=0; q[0][0].value=0x7f7f7f7f7f, q[0][1].value=0;
    		for(int i=1; i<=n; i++) { //找到替换后差值最小的序列编号
    			if(q[i][1].value==-1) continue;
    			if(q[i][0].value-q[i][1].value<q[idx][0].value-q[idx][1].value) idx=i;
    		}
    		if(idx==0) { //不能替换
    			cout << -1;
    			return;
    		}
    		ans=ans-q[idx][0].value+q[idx][1].value; //更新替换后的答案 
    		cout << ans << "\n";
    		q[idx][0]=q[idx][1]; //更新替换后的编号 
    		for(int i=1; i<=n; i++) cout << q[i][0].index-1 << " ";
    	}
    } 
    int main(){
    	cin >> n >> mod;
    	for(int i=1; i<=n; i++) {
    		cin >> x >> a >> b >> c;
    		Make_serial();
    		Get_max(i);
    	}
    	Get_ans();
    	return 0;
    }
    
    • 1

    信息

    ID
    6139
    时间
    1000ms
    内存
    256MiB
    难度
    3
    标签
    递交数
    0
    已通过
    0
    上传者