1. 程式人生 > >bzoj 3598 [ Scoi 2014 ] 方伯伯的商場之旅 ——數位DP

bzoj 3598 [ Scoi 2014 ] 方伯伯的商場之旅 ——數位DP

ems lse ++ href sco i++ pac .cn php

題目:https://www.lydsy.com/JudgeOnline/problem.php?id=3598

數位DP...東看西看:http://www.cnblogs.com/Artanis/p/3751644.html

         https://www.cnblogs.com/MashiroSky/p/6399095.html

好巧妙的思路啊!這樣統計的東西就變得很簡單了;

好美的 dfs!數位DP用 dfs 好像能變得很清楚。

代碼如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace
std; typedef long long ll; ll l,r,f[65][6005],ans; int n,a[65],K; ll dfs1(int pos,int s,bool lim) { if(pos==0)return s; if(!lim&&f[pos][s]!=-1)return f[pos][s]; int end=K-1; ll ret=0; if(lim)end=a[pos]; for(int i=0;i<=end;i++) ret+=dfs1(pos-1,s+i*(pos-1),lim&&(i==end));
if(!lim)f[pos][s]=ret;//!lim! return ret; } ll dfs(int pos,int s,int m,bool lim) { if(s<0)return 0;//! if(pos==0)return s; if(!lim&&f[pos][s]!=-1)return f[pos][s]; int end=K-1; ll ret=0; if(lim)end=a[pos]; for(int i=0;i<=end;i++) { if(pos>=m)ret+=dfs(pos-1
,s+i,m,lim&&(i==end)); else ret+=dfs(pos-1,s-i,m,lim&&(i==end)); } if(!lim)f[pos][s]=ret; return ret; } ll calc(ll x) { int n=0; while(x)a[++n]=x%K,x/=K; memset(f,-1,sizeof f); ll ret=dfs1(n,0,1); for(int i=2;i<=n;i++) { memset(f,-1,sizeof f); ret-=dfs(n,0,i,1); } return ret; } int main() { scanf("%lld%lld%d",&l,&r,&K); printf("%lld\n",calc(r)-calc(l-1)); return 0; }

bzoj 3598 [ Scoi 2014 ] 方伯伯的商場之旅 ——數位DP