 /**//*
題意:?jiǎn)朳1,n]內(nèi)有多少個(gè)數(shù)能被13整除,且包含子串"13"

這題請(qǐng)教了龍教主 Orz

對(duì)于這種[1,n]的,比較好的做法就是逐位統(tǒng)計(jì)
對(duì)于當(dāng)前位bit[i](i之前的所有位已確定),枚舉[0,bit[i]),然后i之后的位自由變化
對(duì)于自由變化的那些情況,可以預(yù)處理出來(lái),那些是不需約束的情況
(感覺(jué)就是按前綴分類(lèi)計(jì)算,含0個(gè)前綴,1個(gè)前綴 的所有小于n的數(shù))

dp1[i][j][k]表示當(dāng)前位為i,數(shù)字為j,余數(shù)為k,有13的個(gè)數(shù)
dp2[i][j][k]表示當(dāng)前位為i,數(shù)字為j,余數(shù)為k,沒(méi)有13的個(gè)數(shù)
數(shù)位統(tǒng)計(jì)時(shí)注意不要重復(fù)計(jì)算了
*/
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

int dp1[11][11][14],dp2[11][11][14];
int ten[11],bit[11];

void init()
  {
memset(dp1,0,sizeof(dp1));
memset(dp2,0,sizeof(dp2));
ten[0] = 1;
for(int i=1;i<10;i++)
ten[i] = ten[i-1]*10;
for(int j=0;j<10;j++)
dp2[0][j][j] = 1;
for(int i=1;i<10;i++)//len
for(int j=0;j<10;j++)
for(int jj=0;jj<10;jj++)
for(int k=0;k<13;k++)
 {
int kk = (ten[i]*j+k)%13;//
dp1[i][j][kk] += dp1[i-1][jj][k];
if(j==1&&jj==3)dp1[i][j][kk] += dp2[i-1][jj][k];
else dp2[i][j][kk] += dp2[i-1][jj][k];
}
}

bool chk(int x)
  {
char str[20];
sprintf(str,"%d",x);
for(int i=0;str[i+1];i++)
if(str[i]=='1' && str[i+1]=='3')return true;
return false;
}
int main()
  {
init();
int n;
while(~scanf("%d",&n))
 {
int nn = n,tot = 0;
while(nn>0)
 {
bit[tot++] = nn%10;
nn/=10;
}
int ans = 0,last = 0,pre = 0;
bool flag = false;
if(chk(n) && n%13 == 0)ans++;
for(int i = tot-1;i>=0;i--)
 {
for(int j = bit[i]-1;j>=0;j--)
 {
for(int k=0;k<13;k++)
 {
int kk = (pre+k)%13;
if(kk==0)
 {
ans += dp1[i][j][k];
if(flag)ans+=dp2[i][j][k];
if(flag==0&&last==1&&j==3)ans += dp2[i][j][k];//這里需要加flag==0!
break; //若flag=1,這種情況就屬于有前綴13的那種情況了
} //n = 1314
} // 在131*時(shí)就已經(jīng)算了1313的情況了
}
if(last==1 && bit[i] ==3)flag = true;
last = bit[i];
pre += bit[i]*ten[i];
}
printf("%d\n",ans);
}
return 0;
}
|
|
常用鏈接
隨筆分類(lèi)
Links
搜索
最新評(píng)論

|
|