D. Roman and Numbers
time limit per test

4 seconds

memory limit per test

512 megabytes

input

standard input

output

standard output

Roman is a young mathematician, very famous in Uzhland. Unfortunately, Sereja doesn't think so. To make Sereja change his mind, Roman is ready to solve any mathematical problem. After some thought, Sereja asked Roma to find, how many numbers are close to number n,
modulo m.

Number x is considered close to number n modulo m,
if:

  • it can be obtained by rearranging the digits of number n,
  • it doesn't have any leading zeroes,
  • the remainder after dividing number x by m equals
    0.

Roman is a good mathematician, but the number of such numbers is too huge for him. So he asks you to help him.

Input

The first line contains two integers: n (1 ≤ n < 1018) and m (1 ≤ m ≤ 100).

Output

In a single line print a single integer — the number of numbers close to number n modulo m.

Sample test(s)
input
104 2
output
3
input
223 4
output
1
input
7067678 8
output
47
Note

In the first sample the required numbers are: 104, 140, 410.

In the second sample the required number is 232.

题意:

给定一个数字n。将n的每一位数字又一次排列,求在这些排列数之中能够被n整除的方法数。

思路1:

数位dp。数字仅仅有18位,能够考虑位压缩。

dp[i][j]表示状态所用的状态为i。前缀模m余j的个数。

枚举下一位选哪一个数来进行状态转移。

用记忆化搜索来实现。注意不能有前导0。

如何解决不反复计算呢,採用的方法是每次转移的时候不反复转移,用一个数组vis[10]来标记选了什么,比方计

算了3之后,后面还有3就不选了,就不会计算反复了。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define maxn 205
#define MAXN 100005
#define mod 100000000
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std; ll n,m,ans,tot,ed;
ll dig[20],dp[1<<18][105]; ll dfs(ll s,ll sy,ll flag)
{
if(s==ed)
{
if(sy==0) return 1;
return 0;
}
if(dp[s][sy]!=-1) return dp[s][sy];
ll i,t,best=0;
bool vis[10]={0};
for(i=0;i<tot;i++)
{
if(vis[dig[i]]||(s&(1<<i))) continue ;
if(flag==0&&dig[i]==0) continue ;
ll ss=s|(1<<i),ty=(sy*10+dig[i])%m;
vis[dig[i]]=1;
best+=dfs(ss,ty,1);
}
dp[s][sy]=best;
return best;
}
void solve()
{
ll i,j,t,x;
x=n;
memset(dig,0,sizeof(dig));
memset(dp,-1,sizeof(dp));
tot=0;
while(x)
{
t=x%10;
dig[tot++]=t;
x/=10;
}
ed=(1<<tot)-1;
ans=dfs(0,0,0);
}
int main()
{
ll i,j,t;
while(~scanf("%I64d%I64d",&n,&m))
{
solve();
printf("%I64d\n",ans);
}
return 0;
}

思路2:

学习了一种新的状压方式,来源于德保

直接依据数码x出现的次数进行状态压缩。比方33211就仅仅须要2*6+1*3+2=17的空间了。利用均值不等式。也差点儿相同仅仅需(ceil(18/10+1)^10)=59049的空间。

并且这样能够用递推来实现。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define maxn 205
#define MAXN 100005
#define mod 100000000
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std; ll n,m,ans,tot;
ll dig[10],dp[60000][105]; ll codeit(ll tmp[]) // 状态压缩
{
ll i,t=0;
for(i=0; i<10; i++)
{
t=t*(dig[i]+1)+tmp[i];
}
return t;
}
void decode(ll s,ll tmp[]) // 从压缩状态中解码 还原状态
{
ll i,t;
for(i=9; i>=0; i--)
{
tmp[i]=s%(dig[i]+1);
s/=(dig[i]+1);
}
}
void solve()
{
ll i,j,t,x=n;
memset(dig,0,sizeof(dig));
while(x)
{
dig[x%10]++;
x/=10;
}
tot=codeit(dig);
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(i=0; i<=tot; i++)
{
ll cnt[10];
decode(i,cnt); // 解码
for(ll k=0; k<10; k++) // 枚举下一位
{
if(cnt[k]>=dig[k]) continue ;
if(i==0&&k==0) continue ;
cnt[k]++;
ll s=codeit(cnt); // 状态压缩
for(j=0; j<m; j++) // 枚举余数
{
dp[s][(j*10+k)%m]+=dp[i][j]; // 转移
}
cnt[k]--;
}
}
ans=dp[tot][0];
}
int main()
{
ll i,j,t;
while(cin>>n>>m)
{
solve();
cout<<ans<<endl;
}
return 0;
}

Codeforces Round #235 (Div. 2) D. Roman and Numbers (数位dp、状态压缩)的更多相关文章

  1. Codeforces Round #235 (Div. 2) D. Roman and Numbers(如压力dp)

    Roman and Numbers time limit per test 4 seconds memory limit per test 512 megabytes input standard i ...

  2. Codeforces Round #235 (Div. 2) D. Roman and Numbers 状压dp+数位dp

    题目链接: http://codeforces.com/problemset/problem/401/D D. Roman and Numbers time limit per test4 secon ...

  3. Codeforces Round #287 (Div. 2) D. The Maths Lecture [数位dp]

    传送门 D. The Maths Lecture time limit per test 1 second memory limit per test 256 megabytes input stan ...

  4. BestCoder Round #52 (div.2) HDU 5418 Victor and World (DP+状态压缩)

    [题目链接]:pid=5418">click here~~ [题目大意]: 问题描写叙述 经过多年的努力,Victor最终考到了飞行驾照. 为了庆祝这件事,他决定给自己买一架飞机然后环 ...

  5. Codeforces Round #267 (Div. 2) C. George and Job(DP)补题

    Codeforces Round #267 (Div. 2) C. George and Job题目链接请点击~ The new ITone 6 has been released recently ...

  6. Codeforces Round #235 (Div. 2)

    A. Vanya and Cards time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  7. Codeforces Round #493 (Div. 2)D. Roman Digits 第一道打表找规律题目

    D. Roman Digits time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  8. Codeforces Round #532(Div. 2) A.Roman and Browser

    链接:https://codeforces.com/contest/1100/problem/A 题意: 给定n,k. 给定一串由正负1组成的数. 任选b,c = b + i*k(i为任意整数).将c ...

  9. Codeforces Round #235 (Div. 2)C、Team

    #include <iostream> #include <algorithm> using namespace std; int main(){ int n,m; cin & ...

随机推荐

  1. 在CentOS下源码安装 Xen并搭建Windows虚拟机

    前言 首先要感谢xing的帮助,在他的指导之下才完成环境的搭建,本文档的部分内容来自他的文档.另外,还要感谢——互联网. 1.       环境介绍 Linux: CentOS 6.3 Xen: Xe ...

  2. 用ATL写简单的ActiveX控件 .

    我正在做的项目需要用读卡器来读数据,由于系统是B/S架构的所以只能把读卡器的驱动封装成一个无界面的ActiveX控件,这样web页面中的js代码才能访问读卡器其实做起来也挺简单的,我用的环境是VS20 ...

  3. POJ - 1185 炮兵阵地 (状态压缩)

    题目大意:中文题目就不多说大意了 解题思路: 1.每行最多仅仅有十个位置,且不是山地就是平原,那么就能够用1表示山地,0表示平原,将每一行的状态进行压缩了 2.接着找出每行能放炮兵的状态.先不考虑其它 ...

  4. EasyUI - Tabs 选项卡标签

    基本效果: 效果图: html代码: <div id="tab"> <div title="tab1" > <p>tab1& ...

  5. sql: sybase 和 oracle 比较

    1. sybase 和 oracle 比较 http://blog.itpub.net/14067/viewspace-1030014/ Oracle采用多线索多进程体系结构 Sybase采用单进程多 ...

  6. QT在Windows控制台下输出

    原地址:http://blog.csdn.net/fjb2080/article/details/9013047 在windows的控制台下输出,需要在pro文件中加入: CONFIG += cons ...

  7. 使用iframe设置frameset的高度

    index.html的页面代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "htt ...

  8. Windows下实战Apache+PHP [转]

        一.Apache 1.下载登陆Apache Lougne(http://www.apachelounge.com/download/),找到最新版本的Apache.笔者下载的是带IPv6和Cr ...

  9. 单选按钮、复选按钮——axure线框图部件库介绍

    有时候发现这做事情坚持下来是一件很不容易的,写教程也一样,不过听到很多朋友对我说 这个全部是图片的教程 对他们入门帮助很多,我就想想 在坚持坚持把基础部分先完善了! 1. 简单的问卷调查: 您的性别? ...

  10. 如何获得getElementById的length这个数值?

    a=document.getElementById("a").innerHTML.length;我觉得你应该这么写 如果是文本框的话document.getElementById( ...