-
B - XHXJ's LIS
- HDU - 4352
- S^(1<<i)把第i位变为0其余的保持不变
- 题意:给出l,r求出L-R之间的数字有哪些是最长上升序列为k的数目通过O(nlogn)的LIS因为是数字只有10个数
- 可以状态压缩模拟LIS过程,最终统计1的个数即可(小细节这里全是真正数字所以数字状态不能由0更新而来,会导致出现前导零情况)
-
#include<bits/stdc++.h> using namespace std; #define ll long long #define maxn 1<<11 ll dp[25][maxn][15],l,r; int k,a[25],t; int getsum(int num) { int cnt=0; while(num) { num&=(num-1); cnt++; } return cnt; } int updata (int num,int ind) { for(int i=ind; i<=9; i++) if(num&(1<<i)) return (num^(1<<i))|(1<<ind); return num|(1<<ind); } ll dfs(int len,int num,bool limit) { if(len==0) return getsum(num)==k; if(!limit&&dp[len][num][k]>=0) return dp[len][num][k]; int up=(limit?a[len]:9); ll ans=0; for(int i=0; i<=up; i++) ans+=dfs(len-1,num==0&&i==0?0:updata(num,i),limit&&i==up); if(!limit) dp[len][num][k]=ans; return ans; } ll solve(ll x) { int len=0; while(x) { a[++len]=x%10; x/=10; } return dfs(len,0,1); } int main() { scanf("%d",&t); memset(dp,-1,sizeof(dp)); for(int T=1; T<=t; T++) { scanf("%lld%lld%d",&l,&r,&k); printf("Case #%d: %lld\n",T,solve(r)-solve(l-1)); } return 0; }
B - XHXJ's LIS -数位DP-nlogn-状压LIS
最新推荐文章于 2020-08-21 10:22:55 发布