子序列个数
来源:互联网 发布:舞蹈教学软件 编辑:程序博客网 时间:2024/06/14 13:53
算法分析:
设 f(k)为k长度的序列的子序列个数,那么很显然有以下推论:
- f(k)的个数包括f(k-1)的个数,因为f(k-1)的每一个都是f(k)的子序列,然后把f(k-1)的每个序列和a[k]组合起来,这些序列也是f(k)的子序列,个数还是f(k-1),载加上单独的a[k],那么
f(k)=2*f(k-1)+1
上面这个表达式是当a[k]和前面的数都不同的时候的情况,如果a[k]在前面出现过的话,那f(k)的个数除了上面那些的话:
- 还需要减去最近一次出现a[k]这个数值的地方-1的子序列个数,因为这些算重复了
- +1也没有了,因为f(a[k]上次出现的位置)包括了a[k]单独算一次的情况
f(k)=2*f(k-1)-f(a[k]上次出现的位置-1)
有了这两个表达式,就是一个完整的递推关系了,a[k]上次出现的位置的保存,可以用一个hash表来存储,这样速度很快,但是题目说a[k]的范围是0到220,那可以用一个220的数组来存储,反正也不会溢出,省得用hash了。
代码:
#include <cstdio>#include <cstring>#include <iostream>using namespace std;const int maxn = 1e6 + 5;const int mod = 1000000007;long long f[maxn]; //避免超intint A[maxn], ls[maxn];int main(){ int n; while(~scanf("%d", &n)) { memset(ls, 0, sizeof(ls)); for(int i = 1; i <= n; i++) { scanf("%d", &A[i]); } for(int i = 1; i <= n; i++) { if(ls[A[i]] == 0) f[i] = (2 * f[i - 1] + 1) % mod; else f[i] = (2 * f[i - 1] - f[ls[A[i]] - 1] + mod) % mod; ls[A[i]] = i; } printf("%lld\n", f[n]); } return 0;}
0 0
- 子序列的个数
- 子序列个数
- 子序列个数
- 子序列个数
- 子序列的个数
- 子序列的个数
- 子序列个数
- 子序列的个数
- 子序列个数
- 子序列个数
- 子序列个数
- 子序列个数
- 子序列个数(DP)
- 1202 子序列个数
- 子序列个数
- 子序列个数
- 子序列个数
- 子序列个数
- IOS开发得到所有的字体样式
- WinCE桌面添加应用程序的快捷方式及自启动 .
- MySQL server has gone away报错原因分析
- iOS 绘图全解(1)
- 推荐:C++论坛
- 子序列个数
- 基于注解的SpringMVC
- spring boot系列一 demo测试
- 如何在Android的xml中添加带<<>>的字符串
- 【让我们再聊聊浏览器资源加载优化】
- iOS —— 检查版本更新
- com.sunspoter.lib.web.struts2.dispatcher.StreamResultX
- 第8周-项目2-Time类中的运算符重载(续)-++、--、>>、<<
- 如何在 C++ 程序中计算时间 .