-
G - B-number
- HDU - 3652
- 题意:A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- string "13" and can be divided by 13. For example, 130 and 2613 are wqb-numbers, but 143 and 2639 are not. Your task is to calculate how many wqb-numbers from 1 to n for a given integer n.太简单不翻译。
- 思路: 数位dp非常模板的题注意按照题意修改各个维度代表的含义即可dp
- 本题第一维一如既往的传递数位第二维传递的是构造一个数的过程中取余13的结果第三维是过程中是否出现过13第四维传递的是上一位是否为1。刚开始少了第四维导至错误,必须要深刻理解dp记忆化的是在当前条件下具有相同状态的数字,只有这样后面才能不用搜索直接取用dp里面的值,所以一定要准确的记忆化,对应这当前题意的限制设置dp数组的维数与含义。
-
#include<bits/stdc++.h> using namespace std; #define maxn 20 #define ll long long ll dp[maxn][15][2][2]; ll num[maxn],n; ll dfs(int len,bool if13,bool pre,int md,bool limit) { if(len==0)return if13&&md==0; if(!limit&&dp[len][md][if13][pre]) return dp[len][md][if13][pre]; ll ans=0,up=limit?num[len]:9; for(int i=0; i<=up; i++) { ll temp=(md*10+i)%13; if(if13||(pre&&i==3)) ans+=dfs(len-1,1,i==1,temp,limit&&i==up); else ans+=dfs(len-1,0,i==1,temp,limit&&i==up); } if(!limit) dp[len][md][if13][pre]=ans; return ans; } ll solve(ll n) { int cnt=0; while(n) { num[++cnt]=n%10; n/=10; } return dfs(cnt,0,0,0,1); } int main() { ios::sync_with_stdio(false); while(cin>>n) cout<<solve(n)<<endl; return 0; }