昨晚做了一个晚上,自己也举了一些案例都过了,结果一直WA,终于搞定了,这题应该是去年网络赛的题目,有点难,看看其他人都是开三维来做的
这里我是开了 四维,不够简洁,但是我觉得比较好理解,记得曾经某位学长 给我讲题目的时候还 开过六维,
dp[i][j][k][l],i位数j开头是否含有13 k=0?1 (mod) 13的值 l,这个就是DP数组的含义
接下来就是对DP数组的预处理了,由是否还有13和对13取模来进行对第i位的决策
计算过程就是记录当前这一位对13取模的余数是多少 和是否已经含有13,正向处理
#include<iostream> #include<cstdio> #include<list> #include<algorithm> #include<cstring> #include<string> #include<queue> #include<stack> #include<map> #include<vector> #include<cmath> #include<memory.h> #include<set> #define ll long long #define eps 1e-8 #define inf 0xfffffff //const ll INF = 1ll<<61; using namespace std; //vector<pair<int,int> > G; //typedef pair<int,int > P; //vector<pair<int,int> > ::iterator iter; // //map<ll,int >mp; //map<ll,int >::iterator p; int dp[12][12][2][15];//dp[i][j][k][l],i位数j开头是否含有13 k=0?1 (mod) 13的值 l int num[12]; void clear() { memset(dp,0,sizeof(dp)); int x = 10; for(int i=0;i<10;i++) dp[1][i][0][i] = 1; for(int i=2;i<=10;i++) { for(int j=0;j<10;j++) { for(int k=0;k<10;k++) { int tmp = (j * x)%13; for(int l=0;l<13;l++) { dp[i][j][1][l] += dp[i-1][k][1][(13 - tmp + l)%13]; if(j == 1 && k == 3) dp[i][j][1][l] += dp[i-1][k][0][(13 - tmp + l)%13]; else dp[i][j][0][l] += dp[i-1][k][0][(13 - tmp + l)%13]; } } } x *= 10; } } int cal(int x) { memset(num,0,sizeof(num)); int ans = 0; int cnt = 0; int len = 1; int tmpx = x; while(tmpx) { cnt++; tmpx /= 10; } cnt--; int tmpcnt = cnt; while(x) { num[tmpcnt--] = x%10; x /= 10; if(x > 0) len *= 10; } int m = 0; int mark = 0; for(int i=0;i<=cnt;i++) { int mod = m%13; for(int j=0;j<num[i];j++) { ans += dp[cnt-i+1][j][1][(13-mod)%13]; if((m/len+j)%100 == 13 || mark == 1) ans += dp[cnt-i+1][j][0][(13-mod)%13]; } m += num[i]*len; if((m/len)%100 == 13) mark = 1; len /= 10; } return ans; } int main() { clear(); int n; while(scanf("%d",&n) == 1) { printf("%d\n",cal(n+1)); } return EXIT_SUCCESS; }
HDU3652 B-number 数位DP,布布扣,bubuko.com
原文:http://blog.csdn.net/yitiaodacaidog/article/details/20550847