冲刺NOIP2017模拟赛R2
| 序列 | 棋盘 | 货车 |
源文件名 | sequence | chess | truck |
读入文件 | sequence.in | chess.in | truck.in |
输出文件 | sequence.out | chess.out | truck.out |
时间限制 | 1s | 3s | 1s |
空间限制 | 16MB | 256MB | 256MB |
最终评测时不开启任何优化开关
序列
经历了上周的惨痛教训,出题人宋伊雪终于意识到了一道送分题的必要性。那么这就是你们看到这道题的原因了!
长话短说,宋伊雪会教你一个生成随机序列的方法,你的目标,是求出这个生成序列的权值最大的连续子串的权值。
输入包含9个正整数A,B,C,D,E,F,A0,B0,n。
在生成好序列之后,对于每个n,如果bn % 2 == 0,那么将an改变为它的相反数。
[输入格式]
仅一行9个正整数A,B,C,D,E,F,A0,B0,n。
每个数的含义参考题面,n代表你需要生成的序列长度
[输出格式]
仅一行输出权值最大的连续子串的权值。
简单地说,连续子串就是连着的一段数字的意思,可以为空。
注意,答案不需要考虑
[样例输入 1]
1 2 3 2 3 5 23 13 5
[样例输出 1]
15382354
[数据范围]
对于20%的数据,满足1 <= n <= 10
另有40%的数据,满足1 <= n <= 1000
另有20%的数据,满足1 <= n <= 1000000
对于100%的数据,满足1 <= n <= 10000000,A,B,C,D,E,F,A0,B0,小于2^31
虽然是道简单的前缀和,只要在计算前缀和的时候顺便更新最小的前缀和,把当前前缀和与这个最小前缀和相减,就可以得到最大的连续子序列。
然而第一次打的时候却意外爆了两个点。
请教钊爷学长后,,
才知道是自己调用了一个传递六个变量的函数,时间复杂度的常数 * 6。
再加上取模操作的运算常数不是1的,于是超了时限。
这里有必要说下,
合理取模。
此题的方程在相加的部分是不会超出 long long 范围的
所以没必要对每步运算都取模
只要相乘操作后取模就行了
科学取模。
顺带一提,取模运算符的优先级是与乘除一档的。。
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long LL;
const LL mo1 = 23333333;
const LL mo2 = 66666666;
LL A,B,C,D,E,F,A0,B0,N;
LL tot,minn,p,q,ans;
/*nline LL js(LL a,LL b,LL c,LL x,LL mo){
return (a * x % mo * x % mo + b * x % mo + c) %mo;
}*/
int main(){
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
cin >> A >> B >> C >> D >> E >> F >> A0 >> B0 >> N;
p = A0; q = B0;
minn = 0; tot = 0; ans = 0;
for(int i = 1; i <= N; i++){
p = (A * p % mo1 * p % mo1 + B * p % mo1 + C) % mo1;
q = (D * q % mo2 * q % mo2 + E * q % mo2 + F) % mo2;
if(q % 2 == 0) p = -p;
tot += p;
minn = min(tot,minn);
ans = max(ans,tot - minn);
if(p < 0) p = -p;
}
cout << ans;
return 0;
}