2 条题解
-
0
我们设 表示如果有 位二进制数,如果第 位放 那么至少是多少名
然后我们用组合数处理就好,最后注意全为 也是一种方案数
#include<iostream> #include<cstdio> #define N 2005 #define int long long using namespace std; bool Test_MLE_start; int T=1,n,m,k,now=0; int ans[N],wch[N][N],C[N][N]; inline int reads(){ char c=getchar(); int sum=0,f=1; while(!isdigit(c)){ if(c=='-') f=-1; c=getchar(); } while(isdigit(c)){ sum=(sum<<3)+(sum<<1)+(c^'0'); c=getchar(); } return sum*f; } inline void files(){ freopen("std.in","r",stdin); freopen("std.out","w",stdout); } inline void clr(){ // Don't forget! } int finds(int L,int R,int x,int cnt){ while(L<R){ int mid=(L+R+1)>>1; if(wch[mid][cnt]<=x) L=mid; else R=mid-1; } return L; } bool Test_MLE_end; signed main(){ // printf("%lf Mb\n",(&Test_MLE_end-&Test_MLE_start-1)/1024.0/1024.0); // files(); // T=reads(); while(T--){ clr(); for(int i=0;i<=N-5;i++){ C[i][0]=1; for(int j=1;j<=i;j++){ C[i][j]=C[i-1][j]+C[i-1][j-1]; } } n=reads(),m=reads(),k=reads(); for(int i=0;i<=n;i++){ for(int j=0;j<=m;j++){ wch[i][j]=1; for(int p=0;p<=j;p++){ wch[i][j]+=C[i-1][p]; } } } // for(int i=0;i<=n;i++){ // for(int j=0;j<=m;j++){ // cout<<wch[i][j]<<" "; // } // puts(""); // } while(k>1&&m){ int nxt=finds(1,n,k,m); // cout<<nxt<<" "<<m<<" "<<wch[nxt][m]<<":"<<k<<"->"; k-=wch[nxt][m],m--; k++; // cout<<k<<"\n"; ans[nxt]=1; } for(int i=n;i>=1;i--) printf("%d",ans[i]); } return 0; } /* 000111010110111100110101100011 000111010110111100110101100011 */ -
0
从高到低依次确定每一位,假设现在是从右往左的第 位,后边还要放 个零,那么剩下的 位就还有 种放法,但题目说是至多 个,所以把组合数累加就可以了。
假设现在他的排名为 ,后面如果放0,有s种放法。那么如果k>s,这一位就应该是1,要k-=s。
#include<bits/stdc++.h> #define int long long using namespace std; int n,m,k; int C[50][50],s[50][50]; int ans[50]; signed main(){ std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); cin>>n>>m>>k; C[1][0]=C[1][1]=1; for(int i=2;i<=n;++i){ C[i][0]=1; for(int j=1;j<=i;++j){ C[i][j]=C[i-1][j]+C[i-1][j-1]; } } s[0][0]=1; for(int j=1;j<=n;++j){ s[0][j]=1; } for(int i=1;i<=n;++i){ s[i][0]=C[i][0]; for(int j=1;j<=n;++j){ s[i][j]=s[i][j-1]+C[i][j]; } } for(int i=n,cnt=0;i>=1;--i){ if(m>cnt&&k>s[i-1][m-cnt]){ k-=s[i-1][m-cnt]; ++cnt; ans[i]=1; } } for(int i=n;i>=1;--i){ cout<<ans[i]; } return 0; }注意求前缀和的时候j=0的也要算,否则最后一位会出错
- 1
信息
- ID
- 244
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- (无)
- 递交数
- 36
- 已通过
- 15
- 上传者