hdu 4055/ZOJ 3543 Number String (计数DP+手动取模+巧妙)

本文介绍了一种优化后的字符串排列算法,通过使用DP方法并结合前缀和技巧来降低时间复杂度至N²级别。该算法适用于求解特定条件下的字符串排列数量问题。

以下为在HDU上测试的时间,手动取模比%快了不少


dp[i][j]表示长度为i的字符串,最后一个数字为j时的排列种数。

字符为 I

如果长的为i-1的字符串都排好了的话,第j位只要找第i-1位的数字比j小的就行

所以就是  dp[i][j]=d[i-1][1]+ d[i-1][2]+ d[i-1][3]+...+d[i-1][j-1]  

字符为 D 时

如果长的为i-1的字符串都排好了的话,只要找第i-1位大于等于j的就行

为什么呢,重点来了

你只要把 j~i-1 每个数都 +1 就变成比 j 大的了!!!而且还顺便把j的位置腾出来了!!!十分的巧妙啊!!!

字符为 ?时只要把之前两种情况加起来就行了

最后用前缀和处理一下储存数据就行了。将复杂度降到了N²

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define mod 1000000007
ll dp[1005][1005];ll sum[1005][1005];

inline int MOD(int x){
    if(x >= 0 && x < mod) return x;
    return x < 0 ? -MOD(-x) + mod : x - mod;
}


int main()
{
    char str[1005];  
    while(scanf("%s",str) != EOF){  
        dp[1][1]=1;
        sum[1][1]=1;
        int len=strlen(str);
        for(int i=2;i<=len+1;i++)
        
        for(int j=1;j<=i;j++)
        {
            if(str[i-2]=='I')
            dp[i][j]=MOD(sum[i-1][j-1]);
            else if(str[i-2]=='D')
            dp[i][j]=MOD(sum[i-1][i-1]-sum[i-1][j-1]+mod);
            else
            dp[i][j]=sum[i-1][i-1];
            
            sum[i][j]=MOD(sum[i][j-1]+dp[i][j]);
        }
        printf("%lld\n",sum[len+1][len+1]);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值