1 条题解
-
0
自动搬运
来自洛谷,原作者为

Anins
AFO搬运于
2025-08-24 22:25:37,当前版本为作者最后更新于2024-09-14 09:23:33,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
[NEERC2015] Generators
题意
有 个序列,对于每个序列给定 ,并按照 进行扩展,每个序列取一个数进行累加,输出对 取模不为 的最大累加和以及每个序列中取出的数的下标,无解输出 。
思路
-
显然 是单调不减的,那么对 取模就是周期函数,只需求出一个周期即可代表整个序列。
-
对每个序列记录对 取模后值不同的最大值和次大值。
-
将每个序列最大值累加,若对 取模不为 ,那么输出。
-
否则考虑将一个最大值替换成次大值,要求前后差值最小。
- 若能替换,则替换后对 取模一定不为 ,进行输出。
- 若不能替换,则意味着无解,输出 。
代码
#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
- 上传者