2 10000 9999 5 1 9999 1 9999 1
19999 22033
/************************************************************************/
附上该题对应的中文题
给n个数A1,A2....An,你可以选择一个区间(也可以不选),区间里每个数x变成f(x),其中f(x)=(1890x+143)mod10007。问最后n个数之和最大可能为多少。
输入有多组数据。 每组数据第一行包含一个整数n.(1≤n≤105) 第二行n个整数A1,A2....An.(0≤Ai≤104) 数据保证 ∑n≤106.
对于每组数据输出一行答案.
2 10000 9999 5 1 9999 1 9999 1
19999 22033
出题人的解题思路:
令Ai=f(Ai)−Ai,然后求一遍最大连续子序列和就能知道最多能增加的值。
首先,先离线求出f(x)的值,对于f(x)-x可以知道数x改变之后是变大了还是变小了,然后套一下最大连续子序列和的模板,就可以求出结果了
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #include<stack> #include<math.h> #include<vector> #include<map> #include<set> #include<cmath> #include<string> #include<algorithm> #include<iostream> #define exp 1e-10 using namespace std; const int N = 100005; const int M = 10005; const int inf = 1000000000; const int mod = 10007; int s[N],a[N],b[N]; __int64 f_max(__int64 a,__int64 b) { return a>b?a:b; } int main() { int n,i,j; __int64 ans,sum,last; for(i=0;i<10000;i++) s[i]=(i*1890+143)%mod-i; while(~scanf("%d",&n)) { for(sum=0,i=1;i<=n;i++) { scanf("%d",&a[i]); sum+=a[i]; b[i]=s[a[i]]; }//printf("%I64d\n",ans); last=ans=0; for(i=1;i <= n;i++) { last=f_max(0,last)+b[i]; ans=f_max(ans,last); } printf("%I64d\n",sum+ans); } return 0; }菜鸟成长记