题目地址:
http://acm.hdu.edu.cn/showproblem.php?pid=3652
题目概述:
给出一个数n,求出1~n中所有包含“13”并且是13的倍数的数的个数。例如13满足条件,而143虽然是13的倍数,不过不包含“13”,所以不满足条件。
大致思路:
这种类型的题应该很容易看出是数位DP,这里设f[i,j,k,l]表示i位数当前位是j,这个数mod13=k的情况,l=1表示包含“13”,l=0表示不包含。
转移的话详见代码。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <ctime>
#include <map>
#include <stack>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define sacnf scanf
#define scnaf scanf
#define scanfi(x) scanf("%d",&x)
#define scanfd(x) scanf("%lf",&x)
#define scanfl(x) scanf("%lld",&x)
#define scanfc(x) scanf("%c",&x)
#define scanfs(x) scanf("%s",&x)
#define maxn 110
#define maxm 10
#define inf 1061109567
#define Eps 0.00001
const double PI=acos(-1.0);
#define mod 1000000007
#define MAXNUM 10000
void Swap(int &a,int &b) {int t=a;a=b;b=t;}
int Abs(int x) {return (x<0)?-x:x;}
typedef long long ll;
typedef unsigned int uint;
int f[11][10][13][2]; //f[i,j,k,l] i位数当前为是j,mod13=k的情况,l=1表示包含13
int num[11];
int power(int a,int b)
{
int ans=1;
while(b)
{
if(b&1) ans*=a;
a*=a;b>>=1;
}
return ans;
}
int calc(int x)
{
int cnt=0,ans=0,temp=0;
while(x)
{
num[cnt++]=x%10;
x/=10;
}
num[cnt]=0;bool flag=false;
for(int i=cnt-1;i>=0;i--)
{
for(int j=0;j<num[i];j++)
{
ans+=f[i+1][j][(13-temp%13)%13][1];
if(flag) ans+=f[i+1][j][(13-temp%13)%13][0];
else if(j==3&&num[i+1]==1) ans+=f[i+1][j][(13-temp%13)%13][0];
}
if(num[i+1]==1&&num[i]==3) flag=true;
temp+=num[i]*power(10,i);
}
return ans;
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
//clock_t st=clock();
int n;
for(int i=0;i<10;i++) f[1][i][i][0]=1;
for(int i=2;i<=10;i++)
{
for(int j=0;j<10;j++)
{
for(int k=0;k<10;k++)
{
for(int l=0;l<13;l++)
{
f[i][j][(l+j*power(10,i-1))%13][1]+=f[i-1][k][l][1];
if(j==1&&k==3)
{
f[i][j][(l+j*power(10,i-1))%13][1]+=f[i-1][k][l][0];
}
else f[i][j][(l+j*power(10,i-1))%13][0]+=f[i-1][k][l][0];
}
}
}
}
while(~scanf("%d",&n))
{
int ans=calc(n+1);
printf("%d\n",ans);
}
//clock_t ed=clock();
//printf("\n\nTime Used : %.5lf Ms.\n",(double)(ed-st)/CLOCKS_PER_SEC);
return 0;
}
来源:https://www.cnblogs.com/CtrlKismet/p/6707750.html