Expection of String HDU - 5576 暴力dp

Frog has just learned how to multiply two numbers. Now he wants to do some exercise.

He wrote a string on the paper, which only contains digits and a single × as the operator. If the × appears at the front or the end of the string, he regards the result as zero, otherwise he does the calculation as a normal multiplication.

After some play, he wonders a new problem: for a initial string, each time he randomly choose two characters and swap their positions. He will do this again and again, say for K times, he wants to know the expected calculation result for the newest string that he gets.

It can be shown that their can be (n2)K ways(Same as (C2n)K) for the whole swap operations, so if the expected result is x, you need to output x×(n2)K
as an integer.
Input
First line contains an integer T, which indicates the number of test cases.

Every test case begins with an integers K, which is the numbers of times the Frog can swap characters.

The second line of each test case contains the string Frog plays with, which only contains digits and exactly one multiplication operator, written as ‘∗’.

⋅ 1≤T≤100.

⋅ the string’s length is L.

⋅ for 70% data, 1≤L≤10 and 0≤K≤5.

⋅ for 95% data, 1≤L≤20 and 0≤K≤20.

⋅ for 100% data, 1≤L≤50 and 0≤K≤50
.
Output
For every test case, you should output ” Case #x: y”, where x indicates the case number and counts from 1 and y is the result.

Because y could be very large, just mod it with 109+7
.
Sample Input

2
1
1*2
2
1*2

Sample Output

Case #1: 2
Case #2: 6

题意:给出一个长度为55的字符串,由数字和字母×组成,每次可以选择任意两个字符交换位置,如果×在两旁则贡献为0,否则贡献就是左边的数加上右边的数,问所有情况的贡献和;
做法:对于两个位置a,b,任意的交换他们里面的数,对于所有的情况,如果×在a,b之间,位置为x,那么贡献就是a*b*pow(10,x-a-1)*pow(10,n-b-1),那么枚举3个位置a,b,c(a < b < c),所有结果中如果b上为×,那么对答案的贡献为a*b*pow(10,x-a-1)*pow(10,n-b-1),枚举3个位置,dfs(x,y,z,d) 代表在进行了d次操作后,a上为x,b上为y,c上为z的情况下的贡献,记忆话搜索就可以了,
ps:有一个地方我调试了很久,就是在递归的过程中我用全局变量保存了一个值,这个值会在递归的过程中发生变化,因此答案是莫名奇妙的,总结就是以后在递归的过程中在不是确切需要的情况下尽量不要使用全局变量,

#include<bits/stdc++.h>
using namespace std;

int dp[15][15][15][55];
char st[55];
int x[55],cnt[15];
int n,k;
int qp[55];
const int mod = 1e9+7;
void add(int &x,int y){
    x += y;
    if(x >= mod) x -= mod;
}
int dfs(int a,int b,int c,int d){
    if(d == k){
        return b == 10 ? a*c : 0;
    }
    if(dp[a][b][c][d] != -1) return dp[a][b][c][d];
    int ret = 0;
    add(ret,dfs(a,c,b,d+1));
    add(ret,dfs(b,a,c,d+1));
    add(ret,dfs(c,b,a,d+1));
    if(n > 4) add(ret,1LL*(n-3)*(n-4)/2*dfs(a,b,c,d+1)%mod);
    int cns[11];

    if(d == k-1){

    }

    for(int i = 0;i <= 10;i ++) cns[i] = cnt[i];
    cns[a]--,cns[b]--,cns[c]--;
    for(int i = 0;i <= 10;i ++){
        int now = cns[i];
        if(now == 0) continue;
        add(ret,1LL*now*dfs(i,b,c,d+1)%mod);
        add(ret,1LL*now*dfs(a,i,c,d+1)%mod);
        add(ret,1LL*now*dfs(a,b,i,d+1)%mod);
   }
    //cout << a << ' '<< b<<' '<< c << ' '<< d<< ' '<< ret <<endl;
    return dp[a][b][c][d] = ret;
}


int main(){
    int T;
    long long tmp = 1;
    for(int i = 0;i < 55;i ++){
        qp[i] = tmp ;
        tmp = tmp*10%mod;
    }
    cin >> T;
    for(int kase = 1;kase <= T;kase ++){
        memset(dp,-1,sizeof(dp));
        scanf("%d",&k);
        scanf("%s",st);
        n =strlen(st);
        memset(cnt,0,sizeof(cnt));
        for(int i = 0;i < n;i ++){
            x[i] = st[i]=='*'?10:st[i]-'0';
            cnt[x[i]]++;
        }
        int ans = 0;
        for(int i = 0;i < n;i ++){
            for(int j = i+1;j < n;j ++){
                for(int k = j+1;k < n;k ++){
                    add(ans,1LL*qp[j-i-1]*qp[n-k-1]%mod*dfs(x[i],x[j],x[k],0)%mod);
                }
            }
        }
        printf("Case #%d: ",kase);
        cout << ans << endl;
    }




    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值