【蓝桥杯-动态规划-灵活解题】Beauty of Array

问题链接ZOJ3872 Beauty of Array

问题简述:参见上文。

题意有点难懂。

给定n个数的序列,求n个数的各个子序列不重复元素和的和。(想做对此题,必须好好理解题意。不是说不要重复了的子串,而是要在子串中去掉重复的元素,就算去掉之后子串之间有重复是无所谓的。

例如3个元素的序列2,3,3,各个子序列就是{2},{2,3},{2,3,3},{3},{3,3},{3}。各个子序列中去掉重复元素后求和,总和就是2+(2+3)+(2+3)+3+3+3=21。

大致思路:这个题需要用动态规划来解。递推函数dp[i]=(i-pos[ai])*ai,其中pos[ai]=i即上一次ai出现的位置。

设一个pos数组,其下标表示输入的数组元素的数值,其数值表示该元素在所有子串中所出现的次数。

为什么要这样?因为经过规律推导发现,每个元素在被依次加进来时,都应该是上一个元素所加进来之后产生的所有子串再加上当前这个新加的元素(动态规划思想出来了),那么就留一个dp一直保留上一次的子串和,dp加上新加的这个元素就是新增子串的和,(当然,子串之中的元素不能重复,所以用(i-pos[a])来保证新增元素的个数(这步很厉害!))。


  1. #include <iostream>  
  2. #include <stdio.h>  
  3. #include <string.h>  
  4.   
  5. const int N = 1000000;  
  6. long long pos[N+1];  
  7.   
  8. using namespace std;  
  9.   
  10. int main()  
  11. {  
  12.     int t, n, a;  
  13.     scanf("%d", &t);  
  14.     while(t--) {  
  15.         memset(pos, 0, sizeof(pos));  
  16.   
  17.         scanf("%d", &n);  
  18.         long long sum = 0, dp = 0;  
  19.         for(int i=1; i<=n; i++) {  
  20.             scanf("%d", &a);  
  21.             dp += (i - pos[a]) * a;  
  22.             sum += dp;  
  23.             pos[a] = i;  
  24.         }  
  25.   
  26.         printf("%lld\n", sum);  
  27.     }  
  28.   
  29.     return 0;  
  30. }  
另外,memset(数组名,想要统一的元素值,sizeof(数组名)),函数用法可以学习一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值