题目链接:http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5496
题意:给定一些数字,要求取连续的一段数,和为其中所有元素和(出现多次只算一次)。问所有取法的和的和。
思路:按照一个一个往里添加元素的思想,dp即可。具体的话设前i-1个元素(inclusive)不重复,i与第j个元素重复,则dp[i] = (i-j)*s[i] + dp[i-1]。简单题。
源码:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#define gmax(a,b) a>b?a:b
#define gmin(a,b) a<b?a:b
using namespace std;
typedef long long ll;
int const MAXN = 100000+5;
int s[MAXN],use[MAXN*10];
ll dp[MAXN];
void check(int n)
{
printf("dp = \n");
for(int i=1; i<=n; i++)
printf("%d ",dp[i]);
printf("\n");
}
int main()
{
int t;scanf("%d",&t);
while(t--){
memset(use,0,sizeof(use));
int n;
ll ans = 0;
scanf("%d",&n);
for(int i=1; i<=n; i++){
scanf("%d",&s[i]);
if(i==1) {dp[i] = s[i];
use[s[i]] = i;
}
else{
// if(i==4)
// printf("use 4 = %d\n",use[s[i]]);
if(use[s[i]]!=0){
// printf("use = %d\n",use[s[i]]);
dp[i] = dp[i-1] + (i-use[s[i]])*s[i];
use[s[i]] = i;
}
else{
use[s[i]] = i;
dp[i] = i*s[i] + dp[i-1];
}
}
ans += dp[i];
// printf("%I64d\n",ans);
}
// check(n);
printf("%lld\n",ans);
}
return 0;
}