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 & ...
随机推荐
- [C#] 网页Html转PDF档(一行程式码解决)
原文 [C#] 网页Html转PDF档(一行程式码解决) 网页转PDF档做法很多( Convert HTML to PDF in .NET ) 这边纪录一下老外最多人加分的那篇做法,使用wkhtmto ...
- Robot Framework与Web界面自动化测试学习笔记:如何判断单选框的选中状态
单选按钮是个常见的html元素,在网页中往往提供一组单选按钮来做选项. 这样在自动化测试用例中需要判断当前选中的按钮是否与预期的一直. 可以这样来操作: ${value} Get Element ...
- Android项目实战手机安全卫士(02)
目录 项目结构图 源代码 运行结果 项目源代码 项目结构图 源代码 清单 01. SplashActivity.java package com.coderdream.mobilesafe.acti ...
- scrapy新浪天气
一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiyanlou 2. 环境介绍 本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到桌面上的程序: LX终端(LXTermin ...
- 基于visual Studio2013解决C语言竞赛题之0703乾坤大挪移
题目
- linux服务之NFS和SAMBA服务
这几种网络文件传输最适合局域网.网络中用FTP 一:NFS服务 nfs(network file system)网络文件系统,改服务依赖于rpcbind服务.client通过rpc訪问server端的 ...
- 前端面试题整理(js)
1.HTTP协议的状态消息都有哪些? HTTP状态码是什么: Web服务器用来告诉客户端,发生了什么事. 状态码分类: 1**:信息提示.请求收到,继续处理2**:成功.操作成功收到,分析.接受3** ...
- 将 mp3 等音乐资源以资源形式嵌入 exe 文件中
引用:http://www.easyx.cn/skills/View.aspx?id=6 本文讲解怎样将 mp3 等音乐资源以资源形式嵌入 exe 文件中,并通过 mciSendString 调用.嵌 ...
- 基于visual Studio2013解决C语言竞赛题之1041反向打印
题目 解决代码及点评 /* 功能:将一个整数(最多是10位数)从低位到高位打印出来, 如该数是12345时,输出应是54321(只占一行) 时间:19:18 201 ...
- VC Office2007界面对话框实现
我们知道VS2008SP1之后,MFC就多了一个功能包,可以快速的建立一个ribbon的界面,视觉样式可以在office 2007蓝.黑等颜色之间切换,这对于单文档/多文档做界面非常方便,而且也蛮好看 ...