CodeForces 401D 數位DP
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=98182#problem/D
Description
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 Input
104 2
3
223 4
1
7067678 8
47
Hint
In the first sample the required numbers are: 104, 140, 410.
In the second sample the required number is 232.
/**
CodeForces 401D 數位DP
題目大意:給定一個數字n,將其所有的位上的數重組後組成新的數,問重組後的數有多少個是m的倍數
解題思路:一開始想著統計0~9十個數各出現了多少個,然後普通dp的,費了半天勁,後來覺得狀態太大無法表示,才想到用數位dp。dp[s][k]表示每個數位上的數使用的狀態為s(5二進位制表示101,那麼就是第一三位上的數已使用,第二位上的數沒有使用)
當前數對m的取模為k的數有多少個。有一個問題就是如果直接dp會重複取的,比如:111 3 答案是1而不是6,那麼用一個
flag陣列表示第i位上bit[i]已用就不會出現重複取的情況了,然後dp一下就可以了。數位dp我用的kuangbin的模板
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long LL;
LL dp[(1<<19)+5][111],n;
int m,bit[25],len;
LL dfs(int pos,int s,int k)
{
if(pos<0&&(s==(1<<len)-1))return (k==0);
if(dp[s][k]!=-1)return dp[s][k];
LL ans=0;
int flag[10];
memset(flag,0,sizeof(flag));
for(int i=0;i<len;i++)
{
if((s&(1<<i))==0&&flag[bit[i]]==0)
{
flag[bit[i]]=1;
ans+=dfs(pos-1,s|(1<<i),(k*10+bit[i])%m);
}
}
dp[s][k]=ans;
return ans;
}
LL solve(LL n)
{
int k=0;
while(n)
{
bit[k++]=n%10;
n/=10;
}
len=k;
int s=0;
LL ans=0;
int flag[10];
memset(flag,0,sizeof(flag));
for(int i=0;i<len;i++)
{
if(bit[i]&&flag[bit[i]]==0)
{
flag[bit[i]]=1;
ans+=dfs(k-2,s|(1<<i),bit[i]%m);
}
}
return ans;
}
int main()
{
while(~scanf("%I64d%d",&n,&m))
{
memset(dp,-1,sizeof(dp));
printf("%I64d\n",solve(n));
}
return 0;
}
/**
123 3
104 2
401 2
7067678 8
*/
相關文章
- CodeForces - 628D (數位dp)
- 【數位dp】Beautiful numbers CodeForces - 55D
- [DP] 數位DP
- 數位 dp
- 【數位dp】學習
- 數位DP小記
- Codeforces 914C Travelling Salesman and Special Numbers:數位dp
- 學習筆記:數位dp筆記
- 數位DP 學習筆記筆記
- 【學習筆記】數位DP筆記
- codeforces 341C Iahub and Permutations(組合數dp)
- 1082. 數字遊戲 (數位DP)遊戲
- 演算法隨筆——數位DP演算法
- hdu5435 數位dp(大數的處理)
- codeforces 148 D 概率dp
- codeforces455A Boredom (裸DP)
- Codeforces 869C The Intriguing Obsession:組合數 or dpGUISession
- Codeforces 461B. Appleman and Tree[樹形DP 方案數]APP
- Codeforces 372B Counting Rectangles is Fun:dp套dp
- Codeforces 180C Letter:dp
- BZOJ 3329 Xorequ:數位dp + 矩陣快速冪矩陣
- Codeforces 895C Square Subsets:狀壓dp【組合數結論】
- Codeforces 158E Phone Talks:dp
- Codeforces 432D Prefixes and Suffixes:KMP + dpKMP
- Codeforces 294B Shaass and Bookshelf:dp
- 【dp】codeforces 837D Round Subset
- 【dp】CodeForces - 623B Array GCDGC
- 【dp】codeforces 830-A Office Keys
- codeforces 148 D Bag of mice(概率dp)
- [筆記]數位dp例題及詳解(更新中)筆記
- BZOJ3329: Xorequ(二進位制數位dp 矩陣快速冪)矩陣
- Codeforces 486D Valid Sets:Tree dp【n遍O(n)的dp】
- 【數位dp】(涉及到處理前導0問題)
- Codeforces Round #358 (Div. 2) D dp
- Codeforces 459E Pashmak and Graph:dp + 貪心
- Codeforces 148D Bag of mice (概率dp)
- 【數位dp入門】51nod 1009 數字1的數量
- Codeforces 893E Counting Arrays:dp + 線性篩 + 分解質因數 + 組合數結論