http://acm.hdu.edu.cn/showproblem.php?pid=5586
Sum
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Problem Description
There is a number sequence
A1,A2....An
,you can select a interval [l,r] or not,all the numbers
Ai(l≤i≤r)
will become
f(Ai)
.
f(x)=(1890x+143)mod10007
.After that,the sum of n numbers should be as much as possible.What is the maximum sum?
Input
There are multiple test cases.
First line of each case contains a single integer n. (1≤n≤105)
Next line contains n integers A1,A2....An . (0≤Ai≤104)
It's guaranteed that ∑n≤106 .
First line of each case contains a single integer n. (1≤n≤105)
Next line contains n integers A1,A2....An . (0≤Ai≤104)
It's guaranteed that ∑n≤106 .
Output
For each test case,output the answer in a line.
Sample Input
2 10000 9999 5 1 9999 1 9999 1
Sample Output
19999 22033
题目大意:给n个数A1,A2....An,你可以选择一个区间(也可以不选),区间里每个数x变成f(x),其中f(x)=(1890*x+143) mod 10007。问最后n个数之和最大可能为多少。
和官方的DP方法不一样,感觉自己的DP方法好像更快点
官方方法:令a[i]=f(a[i])-a[i],然后求一遍最大连续子序列和就能知道最多能增加的值。
个人思路:
DP还是不怎么好,想的时间比较长
经过苦思冥想后,终于想到可以用dp[i][j](j=0,1,2)来表示当前状态
dp[i][0]表示当前未进入置换区间,其只能由dp[i-1][0]转移而来
dp[i][1]表示当前正处于置换区间,可由dp[i-1][0]和dp[i-1][1]转移而来
dp[i][2]表示当前已离开置换区间,可由dp[i-1][1]和dp[i-1][2]转移而来
则状态转移方程为:
dp[i][0]=dp[i-1][0]+a[i];
dp[i][1]=max(dp[i-1][0],dp[i-1][1])+f(a[i]);
dp[i][2]=max(dp[i-1][1],dp[i-1][2])+a[i];
#include <cstdio>
#include <algorithm>
using namespace std;
int n,num,i,dp[2][3];//dp[i&1][0]表示当前还未进入置换区间,dp[i&1][0]表示当前处于置换区间,dp[i&1][2]表示当前已出置换区间
inline int f() {
return (1890*num+143)%10007;
}
int main() {
while(1==scanf("%d",&n)) {
dp[0][0]=dp[0][1]=dp[0][2]=0;
for(i=1;i<=n;++i) {
scanf("%d",&num);
dp[i&1][0]=dp[(i-1)&1][0]+num;
dp[i&1][1]=max(dp[(i-1)&1][0],dp[(i-1)&1][1])+f();
dp[i&1][2]=max(dp[(i-1)&1][1],dp[(i-1)&1][2])+num;
}
printf("%d\n",max(dp[n&1][0],max(dp[n&1][1],dp[n&1][2])));
}
return 0;
}