标签:
Description
Input
Output
Sample Input
13 100 200 1000
Sample Output
1 1 2 2
求出1到n中含有13 且能被13整除的数的个数。
dp1[i][j][k]代表不含13的 i位的 以j开头的 且对13取余 的数的个数
dp2[i][j][k]代表包含13的 i位的 以j开头的 且对13取余 的数的个数
对于边界情况,要判断是不是包含了13 且能不能被13整除,当条件满足时才能被累加。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define LL __int64
LL dp1[12][12][13] , dp2[12][12][13] ;//dp1 i位最高位j 余数为k 不含13
int digit[12] , cnt ;
LL f(int n,int j)
{
LL i , k = j ;
for(i = 0 ; i < n ; i++)
k *= 10 ;
return k ;
}
void init()
{
int i , j , k , l , temp ;
memset(dp1,0,sizeof(dp1)) ;
memset(dp2,0,sizeof(dp2)) ;
for(j = 0 ; j < 10 ; j++)
dp1[1][j][ j%13 ] = 1 ;
for(i = 2 ; i <= 10 ; i++)
{
for(j = 0 ; j < 10 ; j++)
{
temp = f(i-1,j) ;
for(k = 0 ; k < 10 ; k++)
{
for(l = 0 ; l < 13 ; l++)
{
dp2[i][j][ (temp+l)%13 ] += dp2[i-1][k][l] ;
if( j == 1 && k == 3 )
dp2[i][j][ (temp+l)%13 ] += dp1[i-1][k][l] ;
else
dp1[i][j][ (temp+l)%13 ] += dp1[i-1][k][l] ;
}
}
}
}
return ;
}
LL solve(LL temp)
{
memset(digit,0,sizeof(digit)) ;
cnt = 0 ;
while( temp )
{
digit[++cnt] = temp%10 ;
temp /= 10 ;
}
LL ans = 0 , i , j , flag = 0 , k ;
for(j = 0 ; j < digit[cnt] ; j++)
ans += dp2[cnt][j][0] ;
temp = f(cnt-1,digit[cnt]) ;
for(i = cnt-1 ; i > 0 ; i--)
{
for(j = 0 ; j < digit[i] ; j++)
{
for(k = 0 ; k < 13 ; k++)
{
if( (temp+k)%13 == 0 )
ans += dp2[i][j][k] ;
if( (temp+k)%13 == 0 && ( digit[i+1] == 1&& j == 3) )
ans += dp1[i][j][k] ;
else if( (temp+k)%13 == 0 && flag )
ans += dp1[i][j][k] ;
}
}
if( digit[i+1] == 1 && digit[i] == 3 )
flag = 1 ;
temp = temp + f(i-1,digit[i]) ;
}
return ans ;
}
int main()
{
LL n ;
init() ;
int i , j , k ;
while( scanf("%I64d", &n) != EOF )
{
printf("%I64d\n", solve(n+1) ) ;
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/winddreams/article/details/42914787