题目链接:FZU 2129 子序列个数
使用一个数组(map超时了)记录一个数字在之前出现的位置,然后状态转移方程有两个,如果一个数字在之前出现过:dp[i] = (dp[i - 1] * 2 - dp[_map[temp] - 1] + MOD) % MOD;,如果没有出现过:dp[i] = (dp[i - 1] * 2 + 1) % MOD;,这里注意减法取余需要加上MOD,否则可能出现负数。
#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
using namespace std;
const int MAX_N = 1000000 + 100;
const long long MOD = 1000000007;
long long dp[MAX_N];
int _map[MAX_N];
//map <long long, int> _map;
int main()
{
int n;
long long temp;
while(scanf("%d", &n) != EOF)
{
//_map.clear();
memset(dp, 0, sizeof(dp));
memset(_map, -1, sizeof(_map));
scanf("%I64d", &temp);
_map[temp] = 1;
dp[1] = 1;
for(int i = 2; i <= n; i++)
{
scanf("%I64d", &temp);
if(_map[temp] != -1)
dp[i] = (dp[i - 1] * 2 - dp[_map[temp] - 1] + MOD) % MOD;
else
dp[i] = (dp[i - 1] * 2 + 1) % MOD;
_map[temp] = i;
}
printf("%I64d\n", dp[n]);
}
return 0;
}