标签:usaco
开始的时候暴力了一次,但是在第10个点就超时了.后面才知道这个题实际上是一个组合数的题目.在每个位置我们可以选择放0或者1,并且我们可以统计出每种放法后面数的排列数,然后我们可以决定放0或放1,继续这个过程直到最后.
所以重点是计算出dp[i][j],表示i位中至多有j位1.对这个我们可以采用dp的方法来求dp[i][j]=dp[i-1][j]+dp[i-1][j-1];
也可以使用组合数来求dp[i][j]=c[i][0]+c[i][1]+…+c[i][j]
代码如下:
/*
ID: 15674811
LANG: C++
TASK: kimbits
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 50
long long c[maxn][maxn];
int main()
{
freopen("kimbits.in","r",stdin);
freopen("kimbits.out","w",stdout);
long long n,L,I;
scanf("%lld%lld%lld",&n,&L,&I);
memset(c,0,sizeof(c));
c[0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=i;j++)
{
if(j==i||j==0)
c[i][j]=1;
else
c[i][j]=c[i-1][j]+c[i-1][j-1];
}
}
//cout<<c[30][15]<<endl;
for(int i=1;i<=n;i++)
{
long long cnt=0;
for(int j=0;j<=L;j++)
cnt+=c[n-i][j];
if(cnt>=I)
{
printf("0");
}
else
{
printf("1");
L--;
I-=cnt;
}
}
printf("\n");
return 0;
}
/*
ID: 15674811
LANG: C++
TASK: kimbits
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 50
long long dp[maxn][maxn];
int main()
{
//freopen("kimbits.in","r",stdin);
//freopen("kimbits.out","w",stdout);
long long n,L,I;
scanf("%lld%lld%lld",&n,&L,&I);
for(int i=0;i<=n;i++)
{
dp[i][0]=1;
dp[0][i]=1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dp[i][j]=dp[i-1][j]+dp[i-1][j-1];
for(int i=n;i>=1;i--)
{
if(dp[i-1][L]>=I)
{
printf("0");
}
else
{
printf("1");
I-=dp[i-1][L];
L--;
}
}
printf("\n");
return 0;
}
标签:usaco
原文地址:http://blog.csdn.net/acm_lkl/article/details/45176795