题意: 问一个区间内的数字满足能被13整除,且含有子序列13的数字的个数。
采用数位DP, 记录状态dp[pos][sum][statue]表示当前为pos位,前面求和mod13的值为sum,statue状态下的答案。
其中statue==0表示上一位不是1,statue==1表示上一位是1, statue==2表示前面已经出现过13序列了。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int dig[12];
LL dp[15][15][3];// 0- not 1, 1- is 1, 2 - contain 13
LL dfs(int pos, int presum, int statue, int limit)
{
if(pos < 1) return statue==2&&presum%13==0;
if(!limit && dp[pos][presum][statue] != -1)
return dp[pos][presum][statue];
int n = limit ? dig[pos] : 9;
LL res = 0;
for(int i = 0; i <= n; ++i)
{
int nowsum = (presum*10 + i)%13;
int nowstatue = statue;
if(statue == 0 && i == 1)
nowstatue = 1;
if(statue == 1 && i != 1)
nowstatue = 0;
if(statue == 1 && i == 3)
nowstatue = 2;
res += dfs(pos-1, nowsum, nowstatue, limit&&i==n);
}
if(!limit) dp[pos][presum][statue] = res;
return res;
}
LL call(LL x)
{
int len = 0;
while(x)
{
dig[++len] = x%10;
x /= 10;
}
return dfs(len, 0, 0, 1);
}
int main()
{
ios::sync_with_stdio(false);
memset(dp, -1, sizeof(dp));
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif // ONLION_JUDGE
LL x;
while(cin >> x)
{
cout << call(x) << endl;
}
return 0;
}