codeforces401D Roman and Numbers(数位状压dp)

Posted 吃花椒的妙酱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces401D Roman and Numbers(数位状压dp)相关的知识,希望对你有一定的参考价值。

题目大意:给n和m,求有多少方案,使得重新排列n的数位后能整除m,不能有前导0

(n<01e18,m<0100)

思路:数位dp

从高位到低位进行dp,dp[s][k]表示当前集合s(现在选了那几个数)模m后的余数为k的方案数

时间复杂度O(18*(2^18))

核心转移方程,dp[now][(上次余数*10+a[i])%m] += dp[pre][上次余数]

不过这样算会算重复,比如n=111,可以从101,011,110转移过来,所以最后要除以num[i]! (i出现的次数,i从1到9)

因为要排除前导0的情况,我先算最高位的方案数,这样就把0的方案排除了,比如n=210,最高位我算2,1就好了

注意:我们并不关心集合(状态s)的每个1是第几位,我们只关心上个状态的方案数,比如now = 101,我们只要看001和100的方案数,加上的1就现在处理的a[j](默认放在末尾)

(感觉这样写好理解一点,看了网上代码a[i]==0时候要contine不是很理解QAQ)

(语文不好,表达有点混乱。。。)

#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <cstring>
#include <math.h>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define IOS ios::sync_with_stdio(false)
#define INF 0x7f7f7f7f7f7f7f7f
#define inf 0x7f7f7f7f
#define pb push_back
#define int long long
const int N=3e5+10;
int n,m,k;
int num[10];
int dp[(1<<18)][105];
vector<int > v;
void solve()
{
    n = v.size();
    for(int i=0 ;i<v.size() ;i++)//先算第一位,避免算到前导0
    {
        if(v[i])//非0
        {
            dp[1<<i][v[i]%m]=1;
        }
    }
    for(int i=0 ;i<(1<<n) ;i++)//state
    {
        for(int j=0 ;j<v.size() ;j++)//枚举选哪个
        {
            if( i&(1<<j) )
            for(int k=0 ;k<m ;k++)
            {
                dp[i][(k*10+v[j])%m] += dp[i^(1<<j)][k];//转移后  - j = 转移前
            }
        }
    }
    _for(i,0,9)
    {
        _for(j,1,num[i])
        {
            dp[(1<<n)-1][0] /= j;
        }
    }
    cout<<dp[(1<<n)-1][0]<<endl;
}
signed main()
{
//    freopen("data.txt","r",stdin);
    cin>>n>>m;
    while( n )
    {
        v.pb(n%10);
        num[n%10]++;
        n /= 10;
    }
    solve();
}

以上是关于codeforces401D Roman and Numbers(数位状压dp)的主要内容,如果未能解决你的问题,请参考以下文章

CF401D Roman and Numbers

Roman and Browser-罗曼的浏览器 CodeForce1100A 暴力

A.Roman and Browser

Codeforces 997B Roman Digits暴力枚举

D. Roman and Numbers(状压dp)

#Leetcode# 13. Roman to Integer