B - So You Think You Can Count?

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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值