1837: LT说我不服
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 53 Solved: 12
Submit Status Web Board
Description
对于上一道题目LT不服,表示那么简单的题目不屑于去做,所以我们决定加大一下题目的难度,下面是我们LT出的题目:
假如给你一个由n个数组成的序列A1, A2, A3, A4 …… An。你可以选择任意一个大小的区间,将其中的每一个数x变成(x*1888+101)%14507。
求这n个数的最大和可能是多少。
Input
输入有多组数据
每组数据第一行输入一个整数n为序列元素个数。(1 <= n <= 100000)
第二行n个整数A1, A2, A3, A4 …… An。(0 <= Ai <= 10000)
Output
每组样例输出一行答案。
Sample Input
210000 999951 9999 1 9999 1
Sample Output
1999921989
HINT
范围在int内
Source
第一次接触最小子序列的和的算法,提交两次,超时一次,第二次A了。
超时用了分冶的算法, 第二次的算法不好解释的通,我这里就自己写写试试吧(估计也只有自己懂了):从前往后逐项算和,不断地把最大的和保存入变量中,当和小于0时,便停止此轮的运算,从下一个数开始继续算和,直到结束。为什么可以这么算呢?根据个人的理解,既然每逢负数就从下一项开始重新计算,那么后面的最优解肯定是不包括前面的,而前面的最优解已经保存入变量中,如此筛选出被每个负数分开的子序列的和,最优解也一次次的更新,并不会漏解(感觉跟没说一样)。
代码如下:
#include <stdio.h>
int main()
{
int u;
int a[100022],b[100022];
int max,tsum;
while (~scanf ("%d",&u))
{
for (int i=1;i<=u;i++)
{
scanf ("%d",&a[i]);
b[i]=(a[i]*1888+101)%14507;
b[i]=b[i]-a[i];
}
max=0;
tsum=0;
for (int i=1;i<=u;i++)
{
tsum+=b[i];
if (tsum>max)
max=tsum;
if (tsum<0)
{
tsum=0;
continue;
}
}
int cot=0;
for (int i=1;i<=u;i++)
{
cot+=a[i];
}
cot+=max;
printf ("%d\n",cot);
}
return 0;
}
嗯挺短的!算法很重要!