Elissa is so clever girl, even though her age is 5 years only. Yesterday she spent all the day learning how to count. Currently she is able to solve many complex counting questions, so she decided to invent a new counting problem in order to help preparing this contest.
Elissa will give you a string s consisting of digits only (from '0' to '9'), and your task is to count in how many ways you can divide the given string to sub-strings such that each sub-string is a beautiful sub-string.
A beautiful sub-string b is a sub-string from string s, such that b contains unique digits only (i.e. each digit from '0' to '9' can exist at most one time).
Elissa thinks that no one can solve this problem because it is very hard. Can you?
Input
The first line contains an integer n (1 ≤ n ≤ 104), where n is the length of the string s. The second line contains a string s consisting of digits only.
Output
Print the number of ways you can divide the given string to sub-strings such that each sub-string is a beautiful sub-string. Since the number of ways may be too large, print the answer modulo 109 + 7.
题意:分割成子集,然后每个子集中没有相同元素,求最多能有多少种子集分割情况
思路:此乃dp;
从后往前找和它相同的数字,然后从j - i的dp值加起来就是dp【i】,然后如果两个相同数字之间有两个相同的数字,那么我们要求的两个数字之间一定是有隔板的,否则那两个之间的相同的数字是不合法的,也就是从后往前遍历,然后+dp,一直加到出现第二个重复数字之时
然后如果这个数字是第一次出现的话,那么前边的所有情况就会在dp[i]中再次出现并且有前边有隔板和前边无隔板两种情况,就只需要乘2就好了
代码一
#include <bits/stdc++.h>
#define mm(a) memset(a, 0, sizeof(a))
using namespace std;
typedef long long ll;
#define LLu unsigned long long
#define PII pair<ll, ll>
#define xx first
#define yy second
ll gcd(ll a, ll b) {return b ? gcd(b, a%b) : a; }
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 7;
const int mod = 1e9 + 7;
char s[N];
int v[15], w[15];
ll dp[N];
int main()
{
int i, j, k, n, m, p;
cin >> n;
dp[0] = 1;
cin >> s + 1;
for(int i = 1; i <= n; i ++)
{
k = s[i] - '0';
p = v[k];
for(j = i; j > p; j --)
{
p = max(p, (w[s[j] - '0']));
dp[i] = (dp[i] + dp[j - 1]) % mod;
}
w[k] = v[k];
v[k] = i;
}
for(int i = 1; i <= n; i ++) cout << dp[i] << " ";
cout << endl;
return 0;
}
代码二
#include <bits/stdc++.h>
#define mm(a) memset(a, 0, sizeof(a))
using namespace std;
typedef long long ll;
#define LLu unsigned long long
#define PII pair<ll, ll>
#define xx first
#define yy second
ll gcd(ll a, ll b) {return b ? gcd(b, a%b) : a; }
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 7;
const ll mod = 1e9 + 7;
int a[N];
ll dp[N];
int v1[N], v2[N];
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i ++)
{
scanf("%1d", &a[i]);
}
dp[1] = 1;
v1[a[1]] = 1;
int i, j;
for(i = 2; i <= n; i ++)
{
memset(v1, 0, sizeof(v1));
memset(v2, 0, sizeof(v2));
dp[i] = 0;
bool flag = 0;
bool flagg = 0;
bool flaggg = 0;
int k = -1;
for(j = i - 1; j >= 1; j --)
{
dp[i] = (dp[i] + dp[j])%mod;
v2[a[j]] ++;
if(a[i] == a[j])
{
flagg = 1;
break;
}
if(v2[a[j]] >= 2)
{
flag = 1;
break;
}
}
if(flag && flagg) dp[i] = (dp[i]- dp[j])%mod;
else if(!flagg) dp[i] = (dp[i - 1]*(ll)2)%mod;
}
// for(int i = 1; i <= n; i ++)
// cout << dp[i] << " ";
// cout << endl;
cout << dp[n] << endl;
return 0;
}