寻找[0,a]中,既包含"13"又能被13整除的数字的个数(a是每一个输入)
开始的思路是打表过,虽然时间再打表的时候时间长一些,但是应该是可以过的,我自己没有试
我使用的方法:
自己第一个想的思路是,记录下当前状态的余数,当前会否包含"13",每次保存的状态都是这样的,但是这样样例都过不了.......后来一想后面的数字和前面连接判断是否包含"13"的话,如果我前面状态保存的是一个"1"呢?那岂不是没有考虑后面再是"3"的情况,所以将是否包含“13”这一个条件分为三个条件:(1)是否包含13 (2)最后一位为1 (3)最后一位不为1
这样就解决了这个问题,我个人觉得数位DP比较难得地方就在于后面状态和前面状态相互对应时条件的判定
这个题中还有一个数学的小技巧:大整数取模
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <math.h> #include <queue> #define INF 0x3f3f3f3f #define ll long long using namespace std; int n , dp[12][3][13];//状态相同的判断:上一个位置的数字与1判断是否相同,是否都会被13整除,前面位数对于13的余数是否相同 int a[12]; int dfs(int pos, int has,int mod,bool limit)//has:有没有13 、 mod 取模13的余数(大数取模)! { if(pos == -1) return has == 2&& mod == 0; if(!limit && dp[pos][has][mod] != -1) return dp[pos][has][mod]; int up = limit?a[pos]:9; int ans = 0; for(int i = 0;i <= up;i ++) { int temp; if (has == 2 || (has == 1 && i == 3)) temp = 2; else if(i == 1) temp = 1; else temp = 0; ans += dfs(pos-1, temp ,(mod * 10 + i) % 13 ,limit && i==a[pos]); } if(!limit) dp[pos][has][mod] = ans; return ans; } int Solve(int x) { int pos = 0; while(x) { a[pos++] = x % 10; x /= 10; } return dfs(pos-1,0,0,true); } int main() { memset(dp,-1,sizeof(dp)); while(~scanf("%d",&n)) { printf("%d\n",Solve(n)); } }