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.
Input
Process till EOF. In each line, there is one positive integer n(1 <= n <= 1000000000).
Output
Print each answer in a single line.
Sample Input
13 100 200 1000
Sample Output
1 1 2 2
题意:求小于等于n的可以被13整除的并且包含13的数有多少个
用容斥原理n减去不能被13整除的减去不含13的,中间多减了,需要加上既不包含13也不能被13整除的数的个数就是答案
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
ll dp[50][50][50];
ll dp1[25][50];
int a[25];
ll dfs(int pos,int pre,int sta,int sum,int limit)
{
if(pos<0)return sum?1:0;
if(!limit&&dp[pos][sum][sta]!=-1)
return dp[pos][sum][sta];
int up=limit?a[pos]:9;
ll ans=0;
for(int i=0;i<=up;i++)
{
if(pre==1&&i==3)continue;
ans+=dfs(pos-1,i,i==1,(sum*10+i)%13,limit&&i==up);
}
if(!limit) dp[pos][sum][sta]=ans;
return ans;
}
ll dfs1(int pos,int pre,int sta,int limit)
{
if(pos<0)return 1;
if(!limit&&dp1[pos][sta]!=-1)
return dp1[pos][sta];
int up=limit?a[pos]:9;
ll ans=0;
for(int i=0;i<=up;i++)
{
if(pre==1&&i==3)continue;
ans+=dfs1(pos-1,i,i==1,limit&&(i==up));
}
if(!limit) dp1[pos][sta]=ans;
return ans;
}
ll solve(int n)
{
int t=0;
ll tt=n;
ll ans3=n-n/13; //不能整除13的
while(n)
{
a[t++]=n%10;
n/=10;
}
ll ans1=dfs(t-1,-1,0,0,1); //既不能被13整除,也不包含13的
ll ans2=dfs1(t-1,-1,0,1)-1; //不含13的
return tt-ans2-ans3+ans1;//容斥
}
int main()
{
int n;
memset(dp,-1,sizeof(dp));
memset(dp1,-1,sizeof(dp1));
while(~scanf("%d",&n)) printf("%lld\n",solve(n));
return 0;
}