문제의 의미 : 1-N (N <= 1,000,000,000) 번호를 찾고는 기술 (13)로 나눌 것이다. 숫자 13는 서브 문자열의 숫자를 포함한다
해결 방법 : 디지털 DP. LL의 DP는 [중고] 이제, 지금 예비 비트 [iflow [REM] 레코드 [있다] 13가되었는지 여부 앞의 표현이, iflow은 REM 아마도 필요가 나머지를 나타내고,가 감소하는지 여부를 DP 처리를 나타낸다.
코드 :
/******************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;
#define eps 1e-8
const double pi=acos(-1.0);
typedef long long LL;
const int Max=10100;
const int INF=1000000007;
LL dp[20][20][2][2][15];
int reminder[20];
int num[30];
LL dfs(int pre,int now,bool have,bool iflow,int rem)
{
if(pre==0)
return have&&rem==0;
if(dp[pre][now][have][iflow][rem]!=-1)
return dp[pre][now][have][iflow][rem];
int en=iflow? 9 : num[pre-1];
LL ans=0;
for(int i=0;i<=en;i++)
{
int tool=((rem-(i*reminder[pre-1])%13)+13)%13;
if(now==1&&i==3)
ans+=dfs(pre-1,i,1,iflow||i!=en,tool);
else
ans+=dfs(pre-1,i,have,iflow||i!=en,tool);
}
return dp[pre][now][have][iflow][rem]=ans;
}
void init()
{
reminder[0]=1;
for(int i=1;i<=10;i++)
reminder[i]=(reminder[i-1]*10)%13;
}
LL solve(LL n)
{
int p=0;
memset(dp,-1,sizeof dp);
while(n)
{
num[p++]=n%10;
n/=10;
}
LL ans=0;
for(int i=0;i<=num[p-1];i++)
{
int tool=(i*reminder[p-1])%13;
ans+=dfs(p-1,i,0,i!=num[p-1],(13-tool)%13);
}
return ans;
}
int main()
{
int n;
init();
while(cin>>n)
{
cout<<solve(n)<<'\n';
}
return 0;
}