bzoj3598 [Scoi2014]方伯伯的商场之旅
2018-03-11 16:43
429 查看
数位dp,我们肯定枚举集合的位置,但是如果每次都重新dp的话会很麻烦,所以我们可以先钦定在最低位集合,dp出代价,然后再一步步找到正确的集合点,每次更改的代价也dp算就好了。
View Code
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #define int long long using namespace std; int L,R,K; int a[66]; int f[66][1500]; int dfs(int pos,int sum,int lim){ if(!pos)return sum; if(!lim&&f[pos][sum]!=-1)return f[pos][sum]; int up=lim?a[pos]:K-1; int ans=0; for(int i=0;i<=up;i++) ans+=dfs(pos-1,sum+(pos-1)*i,lim&&(i==up)); if(!lim)f[pos][sum]=ans; return ans; } int dfs(int pos,int zd,int sum,int lim){ if(sum<0)return 0; if(!pos)return sum; if(!lim&&f[pos][sum]!=-1)return f[pos][sum]; int up=lim?a[pos]:K-1; int ans=0; for(int i=0;i<=up;i++){ if(pos>=zd)ans+=dfs(pos-1,zd,sum+i,lim&&(i==up)); else ans+=dfs(pos-1,zd,sum-i,lim&&(i==up)); } if(!lim)f[pos][sum]=ans; return ans; } int work(int x){ int pos=0; while(x){ a[++pos]=x%K; x/=K; } memset(f,-1,sizeof f); int ans=dfs(pos,0,1); for(int i=2;i<=pos;i++){ memset(f,-1,sizeof f); ans-=dfs(pos,i,0,1); } return ans; } signed main(){ scanf("%lld%lld%lld",&L,&R,&K); printf("%lld\n",work(R)-work(L-1)); return 0; }
View Code
相关文章推荐
- bzoj3598[SCOI2014]方伯伯的商场之旅
- 【BZOJ3598】【SCOI2014】方伯伯的商场之旅
- 【bzoj 3598】: [Scoi2014]方伯伯的商场之旅
- 【数位dp】[Scoi2014] bzoj3598 方伯伯的商场之旅
- bzoj 3598 [Scoi2014]方伯伯的商场之旅 数位dp
- bzoj 3598: [Scoi2014]方伯伯的商场之旅【数位dp】
- BZOJ3598 [Scoi2014]方伯伯的商场之旅
- 【bzoj3598】 Scoi2014—方伯伯的商场之旅
- [BZOJ3598]-[Scoi2014]方伯伯的商场之旅-数位dp
- 【bzoj3598】: [Scoi2014]方伯伯的商场之旅
- [BZOJ3598][SCOI2014]方伯伯的商场之旅(数位DP,记忆化搜索)
- bzoj3598 [Scoi2014]方伯伯的商场之旅
- BZOJ3598[Scoi2014]方伯伯的商场之旅 数位DP
- bzoj3594 [Scoi2014]方伯伯的玉米田
- bzoj3594 [Scoi2014]方伯伯的玉米田
- BZOJ 3594 [Scoi2014]方伯伯的玉米田
- bzoj 3594: [Scoi2014]方伯伯的玉米田 dp树状数组优化
- 【双Treap】[Scoi2014] bzoj3595 方伯伯的Oj
- BZOJ_P3594 [Scoi2014]方伯伯的玉米田(动态规划+二维树状数组优化)
- 【bzoj 3594】[Scoi2014]方伯伯的玉米田