Codeforces Round #235 (Div. 2) D. Roman and Numbers (数位dp、状态压缩)
4 seconds
512 megabytes
standard input
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.
The first line contains two integers: n (1 ≤ n < 1018) and m (1 ≤ m ≤ 100).
In a single line print a single integer — the number of numbers close to number n modulo m.
104 2
3
223 4
1
7067678 8
47
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、状态压缩)的更多相关文章
- 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 ...
- 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 ...
- 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 ...
- BestCoder Round #52 (div.2) HDU 5418 Victor and World (DP+状态压缩)
[题目链接]:pid=5418">click here~~ [题目大意]: 问题描写叙述 经过多年的努力,Victor最终考到了飞行驾照. 为了庆祝这件事,他决定给自己买一架飞机然后环 ...
- 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 ...
- Codeforces Round #235 (Div. 2)
A. Vanya and Cards time limit per test 1 second memory limit per test 256 megabytes input standard i ...
- 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 ...
- 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 ...
- Codeforces Round #235 (Div. 2)C、Team
#include <iostream> #include <algorithm> using namespace std; int main(){ int n,m; cin & ...
随机推荐
- CodeForces 228D. Zigzag(线段树暴力)
D. Zigzag time limit per test 3 seconds memory limit per test 256 megabytes input standard input out ...
- mysql导入sql文件过大或连接超时的解决的方法
前段时间出差在现场开发的时候,导入数据库老是出问题.最后发现了一个奇妙sql语句交给实施,仅仅要导入出错就把例如以下语句运行就能够了.至今屡试不爽. set global max_allowed_pa ...
- QQ登录-第三方SDK的接入总结
由于项目的需要,使用了[QQ登录]SDK 的相关功能! 1.集成[QQ登录]SDK [QQ登录]SDK下载地址: http://wiki.open.qq.com/wiki/website/SD ...
- 搭建python集成开发环境.
需要搭建的内容一共有三项, python ,wxpython 以及spe. 其中spe 是python 的可视化集成开发环境(ide) , 其需要python GUI图形库wxpython的支 ...
- MFC网页访问的实现示例
本示例使用MFC 类CInternetSession 建立连接,使用 CHttpFile读取内容. 首先,建立一个MFC对话框项目,界面如下: 1. 添加头文件: #include <afxin ...
- android 按字母搜索
在看Oplayer的时候看见滑动字母来实现listView的内容搜索,所以就把里面的核心的函数扣除来做了一个demo,分为两部分一个是布局,另一个就是代码了,具体的如下: 布局: <?xml v ...
- BZOJ 1305 CQOI2009 dance跳舞 二分答案+最大流
题目大意:给定n个男生和n个女生,一些互相喜欢而一些不.举行几次舞会,每次舞会要配成n对.不能有同样的组合出现.每一个人仅仅能与不喜欢的人跳k次舞,求最多举行几次舞会 将一个人拆成两个点.点1向点2连 ...
- Swift - 使用NSURLSession加载数据、下载、上传文件
NSURLSession类支持三种类型的任务:加载数据.下载和上传.下面通过样例分别进行介绍. 1,使用Data Task加载数据 使用全局的sharedSession()和dataTaskWithR ...
- (摘录)MSMQ的简单介绍
MSMQ(MicroSoft Message Queue,微软消息队列)是在多个不同的应用之间实现相互通信的一种异步传输模式,相互通信的应用可以分布于同一台机器上,也可以分布于相连的网络空间中的任 ...
- 重操JS旧业第四弹:Date与Global对象
1 Date原理 Date类型表示时间,js中采用UTC国际协调时间,以1971年1月1日0分0秒0微秒开始,经过的毫秒数来表示时间,比如一年的时间计算 1分:1000*60: 1小时:1000(毫秒 ...