一點廢話:
本沙茶從昨天上午下午到現在一直看這鬼東西。。噁心死了啊有木有!!
以前做過一次windy數,代碼調了一億年...
經過兩天的專題訓練,數位dp一點從不會到入了一點門了吧。
以前是什麼都不會,不會想也不會寫。現在至少稍微能寫一些大水題了。。
(其實還是什麼都不會)
好了不說廢話了。
先說寫法:
入門題目:
(一)Bomb
#include <cstdio>
#include <algorithm>
#define rep(i,l,r) for (int i=l;i<=r;++i)
#define per(i,r,l) for (int i=r;i>=l;--i)
typedef long long LL;
LL f[20][3];
void Prep(){
f[0][0]=1;
rep(i,1,19){
f[i][0]=9*f[i-1][0]+8*f[i-1][1];
f[i][1]=f[i-1][0]+f[i-1][1];
f[i][2]=f[i-1][1]+10*f[i-1][2];
}
}
LL count(LL x){
int len=0,a[22];LL res=0;
bool exist=0;
while (x) a[++len]=x%10,x/=10;a[len+1]=-1;
per(i,len,1){
res+=f[i-1][2]*a[i];//-1+1
if (exist) res+=(f[i-1][0]+f[i-1][1])*a[i];
if (!exist&&a[i]>4) res+=f[i-1][1];
if (a[i+1]==4&&a[i]==9) exist=true;
}
if (exist) res++;
return res;
}
LL n;int T;
int main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
Prep();
scanf("%d",&T);
while (T--){
scanf("%I64d",&n);
printf("%I64d\n",count(n));
}
}
#include <cstdio>
#include <algorithm>
#define rep(i,l,r) for (int i=l;i<=r;++i)
typedef long long LL;
LL f[25][4];int a[25];
LL dfs(int pos,int u,bool lim){
if (pos<=0) return u==2;
if (!lim&&f[pos][u]!=-1) return f[pos][u];
LL res=0;
int top=lim?a[pos]:9;
rep(i,0,top){
int v=u;
if (u==1&&i==9) v=2;
if (u==1&&i!=9&&i!=4) v=0;
if (u==0&&i==4) v=1;
res+=dfs(pos-1,v,lim&&i==top);
}
//printf("%d %d %d %d\n",pos,u,lim,res);
return lim?res:(f[pos][u]=res);
}
LL count(LL x){
int pos=0;
while (x) a[++pos]=x%10,x/=10;a[pos+1]=-1;
return dfs(pos,0,1);
}
int main(){
freopen("a.in","r",stdin);
freopen("c.out","w",stdout);
memset(f,-1,sizeof f);
int T;LL n;
scanf("%d",&T);
rep(i,1,T){
scanf("%I64d",&n);
printf("%I64d\n",count(n));
}
}
(二)不要62
#include <cstdio>
#include <algorithm>
#define per(i,r,l) for (int i=r;i>=l;--i)
#define rep(i,l,r) for (int i=l;i<=r;++i)
int f[10][10];
int pow[10];
void prep(){
rep(i,0,9) f[1][i]=(i==4?0:1);
pow[1]=1;
rep(i,2,9) rep(j,0,9){
pow[i]=pow[i-1]*10;
rep(k,0,9)
if (j!=4&&!(j==6&&k==2)) f[i][j]+=f[i-1][k];
}
}
int count(int x){
int res=0,len=1,u=-1,v=-1;
while (x>=10*pow[len]) len++;
per(i,len,1){
int u=x/pow[i];
x-=u*pow[i];
rep(j,0,u-1) if (!(v==6&&j==2))res+=f[i][j];
if ((v==6&&u==2)||u==4) break;
if (i==1) res++;
v=u;
}
return res;
}
int n,m;
int main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
prep();
while (scanf("%d%d",&n,&m)!=EOF){
if (n+m==0) return 0;
printf("%d\n",count(m)-count(n-1));
}
}
(三)windy數
/*
f[i][j]->第i位爲j之內的個數
f[i][j]=Sum{f[i-1][k]} abs(j-k)>=2
*/
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
LL Base[12];
LL f[12][10];//f[i][j]->位數i 最高位爲j 的個數
void preW()
{
Base[1]=1;
for (int i=2;i<=11;++i)Base[i]=10*Base[i-1];
for (int i=0;i<=9;++i) f[1][i]=1;
for (int i=2;i<=11;++i)
for (int j=0;j<=9;++j)
for (int k=0;k<=9;++k)
if (abs(j-k)>=2) f[i][j]+=f[i-1][k];
}
LL Count(LL n)
{
if (n==0) return 0;
LL ret=0;
int p=1;
while (Base[p+1]<=n){
for (int i=1;i<=9;++i)
ret+=f[p][i];
p++;
}
int pre=n/Base[p];
for (int i=1;i<=pre-1;++i)
ret+=f[p][i];
if (p==1) return ret+1;//本身也是
n-=pre*Base[p];
int now=n/Base[p-1];
for (int i=p-1;i>=1;--i){
for (int j=0;j<now;++j)
if (abs(j-pre)>=2)
ret+=f[i][j];
if (abs(pre-now)<2) break;//後面的都不能
if (i!=1){
pre=now;
n-=pre*Base[i];
now=n/Base[i-1];
}
else
ret++; //i==1時abs(pre-now)<2 -->自己也是
}
return ret;
}
int main(){
preW();
LL n,m;
scanf("%lld%lld",&n,&m);
printf("%lld\n",Count(m)-Count(n-1));
}
(四)B-number
#include <cstdio>
#include <algorithm>
#define per(i,r,l) for (int i=r;i>=l;--i)
#define rep(i,l,r) for (int i=l;i<=r;++i)
typedef long long LL;
int f[12][10][14][2];
LL pow[12];
void Preprocess(){
f[0][0][0][0]=1;pow[1]=1;
rep(i,2,11) pow[i]=pow[i-1]*10;
rep(i,1,10) rep(j,0,9){
rep(k,0,9) rep(mod,0,12){
if (j==1&&k==3){
f[i][j][((LL)j*pow[i]+mod)%13][1]+=f[i-1][k][mod][0]+f[i-1][k][mod][1];
}else{
f[i][j][((LL)j*pow[i]+mod)%13][0]+=f[i-1][k][mod][0];
f[i][j][((LL)j*pow[i]+mod)%13][1]+=f[i-1][k][mod][1];
}
}
}
}
int count(int x){
int res=0,mod=0,len=1,v=-1,u=-1;bool exist13=0;
while(x>=pow[len+1]) len++;
per(i,len,1){
u=x/pow[i];x-=u*pow[i];
rep(j,0,u-1){
res+=f[i][j][(13-mod)%13][1];
if (exist13||(v==1&&j==3)){
res+=f[i][j][(13-mod)%13][0];
}
}
if (v==1&&u==3)exist13=true;//!!
mod=(u*pow[i]+mod)%13;
if (i==1&&exist13&&mod==0) res++;
v=u;
}
return res;
}
int n;
int main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
Preprocess();
while (scanf("%d",&n)!=EOF)
printf("%d\n",count(n));
}
(五)Amount of Degrees
#include <cstdio>
#include <algorithm>
#define rep(i,l,r) for (int i=l;i<=r;++i)
#define per(i,r,l) for (int i=r;i>=l;--i)
int f[33][33];
void Prep(){
f[0][0]=1;
rep(i,1,31){
f[i][0]=1;
rep(j,1,i) f[i][j]=f[i-1][j]+f[i-1][j-1];
}
}
int count(int x,int k,int b){
int len=0,res=0,a[33];
while (x) a[++len]=x%b,x/=b;
per(i,len,1){
if (a[i]==1) res+=f[i-1][k--];
if (a[i]>1){res+=f[i-1][k]+f[i-1][k-1];break;}
if (k==0) res++;
if (k<=0) break;
}
return res;
}
int x,y,k,b;
int main(){
Prep();
while(scanf("%d%d%d%d",&x,&y,&k,&b)!=EOF)
printf("%d\n",count(y,k,b)-count(x-1,k,b));
}
(六)self 同類分佈
#include <cstdio>
#include <cstring>
#include <algorithm>
#define rep(i,l,r) for(int i=l;i<=r;++i)
#define per(i,r,l) for(int i=r;i>=l;--i)
typedef long long LL;
LL f[20][173][173];int MOD;
LL pow[20];
LL dfs(int pos,int sum,int mod,bool lim,int a[]){
if (pos*9<sum) return 0;
if (pos<=0) return sum==0&&mod==0;
if (!lim&&~f[pos][sum][mod]) return f[pos][sum][mod];
int top=lim?a[pos]:9;LL res=0;
rep(i,0,top){
int s=sum-i,m=(int)(((LL)mod+(LL)i*pow[pos])%(LL)MOD);
if (s<0) break;
res+=dfs(pos-1,s,m,lim&&i==top,a);
}
return lim?res:(f[pos][sum][mod]=res);
}
int a[20],b[20];
LL count(LL x,LL y){
int lena=0,lenb=0;LL res=0;
while (y) b[++lenb]=y%10,y/=10;
while (x) a[++lena]=x%10,x/=10;
for (int i=1;i<=lenb*9;++i){
memset(f,-1,sizeof f);MOD=i;
res+=dfs(lenb,i,0,1,b);
res-=dfs(lena,i,0,1,a);
}
return res;
}
LL x,y;
int main(){
pow[1]=1;
rep(i,2,19) pow[i]=pow[i-1]*10;
scanf("%lld%lld",&x,&y);
printf("%lld\n",count(x-1,y));
}