usaco 3.2 Stringsobits 数位dp
Kim Schrijvers
Consider an ordered set S of strings of N (1 <= N <= 31) bits. Bits, of course, are either 0 or 1.
This set of strings is interesting because it is ordered and contains all possible strings of length N that have L (1 <= L <= N) or fewer bits that are `1'.
Your task is to read a number I (1 <= I <= sizeof(S)) from the input and print the Ith element of the ordered set for N bits with no more than L bits that are `1'.
PROGRAM NAME: kimbits
INPUT FORMAT
A single line with three space separated integers: N, L, and I.
SAMPLE INPUT (file kimbits.in)
5 3 19
OUTPUT FORMAT
A single line containing the integer that represents the Ith element from the order set, as described.
SAMPLE OUTPUT (file kimbits.out)
10011
求二进制长度为N(可包括前导0)的1的个数不超过L的第I个数。
反着想,设第I个数为m,数位dp可以很轻松地求出[0,m]的符合条件(二进制长度为N(可包括前导0)的1的个数)的数的个数k,显然m是第k个数。
因此直接二分判断就可以了。
/* ID: xidian5601 PROG: kimbits LANG: C++ */ #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1e9+10; ll N,L,I; ll f[40][40]; int num[40],len; ll dfs(int i,int cnt,int e) { if(i==-1) return cnt<=L; if(!e&&~f[i][cnt]) return f[i][cnt]; ll res=0; int u=e?num[i]:1; REP(d,0,u){ if(cnt+d<=L) res+=dfs(i-1,cnt+d,e&&d==u); } return e?res:f[i][cnt]=res; } ll F(ll n) { len=0; while(n){ num[len++]=n%2; n/=2; } return dfs(len-1,0,1); } int cnt(ll n) { int res=0; while(n){ res+=n%2; n/=2; } return res; } ll bin(ll l,ll r,ll kth) { while(l<=r){ ll m=(l+r)>>1; ll t=F(m),c=cnt(m); if(c<=L&&t==kth) return m; if(t==kth&&c>L) r=m-1; else if(t>kth) r=m-1; else l=m+1; } } void Print(ll n) { len=0; while(n){ num[++len]=n%2; n/=2; } REP(i,len+1,N) printf("0"); for(int i=len;i>=1;i--) printf("%d",num[i]);puts(""); } int main() { //freopen("in.txt","r",stdin); freopen("kimbits.in","r",stdin); freopen("kimbits.out","w",stdout); while(cin>>N>>L>>I){ memset(f,-1,sizeof(f)); Print(bin(0,(1LL<<N)-1,I)); } return 0; }
没有AC不了的题,只有不努力的ACMER!