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 & ...
随机推荐
- 高级UIKit-06(UIImagePickerController)
[day07-1-getSystemImage]:获取系统相册 UIImagePickerController图片采集控制器 picker采集者,采摘者 该方法继承自:UINavigationCont ...
- 转:携程App的网络性能优化实践
http://kb.cnblogs.com/page/519824/ 携程App的网络性能优化实践 受益匪浅的一篇文章,让我知道网络交互并不是简单的传输和接受数据.真正的难点在于后面的性能优化 下面对 ...
- ls命令显示可执行的文件 ls -F
ls命令显示可执行的文件 ls -F
- 基于visual Studio2013解决C语言竞赛题之0608水仙花函数
题目 解决代码及点评 /* 功能:写一函数判断某数是否"水仙花数",所谓"水仙花数"是指一个三位数, 其各位数字立方和等于该数本身. */ #includ ...
- 有关android工程的构建脚本(build.xml)的学习
学习[android-sdk-linux根目录]/tools/ant/build.xml,觉得如下几点很有用,记录之 1)ant脚本中属性值是于前置定义优化的原则,即属性发生重复定义时,前面定义的值不 ...
- android 从其他app接收分享的内容
Receiving Content from Other Apps[从其他app接收分享的内容] 就像你的程序能够发送数据到其他程序一样,其他程序也能够简单的接收发送过来的数据.需要考虑的是用户与你的 ...
- 搭建Windows SVN服务器及TortoiseSVN使用帮助和下载
搭建Windows SVN服务器: 用的SVN服务器通常为外部,例如Google Code的服务器,不过,做为一个程序开发人员,就算自己一个人写程序,也应该有一个SVN版本控制系统,以便对开发代码进行 ...
- winform利用代码将控件置于顶端底端
有时,我们可能动态的添加控件,并准备将其置于对顶层或最底层.实现的方法有两个: 一种方法是在WinForm窗体中使用Controls控件集的SetChildIndex方法,该方法将子控件设定为指定的索 ...
- JavaWeb图表插件的小研究
背景 近期的一个项目中,对数据的统计分析有非常大的要求,这就要求有一款非常强大的报表.图表插件.因此,组长给分了任务.让我们各自去研究不同的图表插件.用了一两天的时间,对java这块的图表插件做了一个 ...
- Qt遍历图片文件
原地址:http://blog.sina.com.cn/s/blog_5c70dfc80100tgff.html //实现遍历某个文件下的图片文件 //如果想遍历其余类型文件,方法也一样,只需简单修改 ...