You’re transmitting an n -bits unsigned integer k through a simulated
network. The i -th bit counting from left is transmitted at time i
(e.g. 4-bit unsigned integer 5 is transmitted in this order: 0-1-0-1).
The network delay is modeled as follows: if a bit is transmitted at
time i , it may arrive at as early as i + 1 and as late is i + d + 1 ,
where d represents the maximal network delay. If more than one bit
arrived at the same time, they could be received in any order.For example, if you’re transmitting a 3-bit unsigned integer 2 (010)
for d = 1 , you may receive 010, 100 (first bit is delayed) or 001
(second bit is delayed).Write a program to find the number of different integers that could be
received, and the smallest/largest ones among them.Input
The input contains several test cases. Each case consists of three
integers n, d, k (1 ≤ n ≤ 64, 0 ≤ d ≤ n, 0 ≤ k < 2n) ,
the number of bits transmitted, the maximal network delay, and the
integer transmitted. The last test case is followed by a single zero,
which should not be processed.Output
For each test case, print the case number and the number of different
integers that could be received, followed by the minimal and maximal
one among them.
首先可以确定,0和1自己之间的顺序没有关系,需要调整的只是0和1之间的顺序。
比较好解决的是最大值/最小值,贪心地把0/1放在后面即可。
用dp[i][j]表示接受了i个0和j个1的方案数,考虑接下来接收的是0还是1。如果第j+1个1可以放在第i+1个0后头,那下一位就可以接收0,也就是dp[i+1][j]+=dp[i][j]。接收1同理。
#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL unsigned long long
int p0[100],p1[100],cnt0,cnt1,n,d;
LL k,dp[100][100];
vector<int> v[100];
bool cmp(int a,int b)
{
return a>b;
}
void init()
{
int i;
cnt0=cnt1=0;
for (i=n-1;i>=0;i--)
if (k&(1LL<<i))
p1[++cnt1]=-i;
else
p0[++cnt0]=-i;
}
LL count()
{
int i,j;
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for (i=0;i<=cnt0;i++)
for (j=0;j<=cnt1;j++)
{
if (i<cnt0&&(j==cnt1||p1[j+1]+d>=p0[i+1]))
dp[i+1][j]+=dp[i][j];
if (j<cnt1&&(i==cnt0||p0[i+1]+d>=p1[j+1]))
dp[i][j+1]+=dp[i][j];
}
return dp[cnt0][cnt1];
}
LL findmin()
{
int i,j;
for (i=n-1;i>=0;i--)
v[i].clear();
for (i=n-1;i>=0;i--)
if (k&(1LL<<i))
v[max(0,i-d)].push_back(1);
else
v[i].push_back(0);
LL ret=0;
for (i=n-1;i>=0;i--)
{
sort(v[i].begin(),v[i].end());
for (j=0;j<v[i].size();j++)
ret=ret*2+v[i][j];
}
return ret;
}
LL findmax()
{
int i,j;
for (i=n-1;i>=0;i--)
v[i].clear();
for (i=n-1;i>=0;i--)
if (k&(1LL<<i))
v[i].push_back(1);
else
v[max(0,i-d)].push_back(0);
LL ret=0;
for (i=n-1;i>=0;i--)
{
sort(v[i].begin(),v[i].end(),cmp);
for (j=0;j<v[i].size();j++)
ret=ret*2+v[i][j];
}
return ret;
}
int main()
{
int K=0;
while (cin>>n>>d>>k)
{
init();
cout<<"Case "<<++K<<": "<<count()<<" "<<findmin()<<" "<<findmax()<<endl;
}
}