CodeForces AIM Tech Round 3 (Div. 2) D
智障题,但就是没想出来。
传送门,http://codeforces.com/contest/709/problem/D
题目大意:
给定四个数a00 , a01 , a10 , a11 , 请构造序列A , 使得其中有a00个{0,0}子序列 , a01个{0,1}子序列 , 等等。
若不能构造输出
Impossible
(我打成了
Inpossible
是什么鬼)
解法 :
首先有
a00=C(num[0],2)
、
a11=C(num[1],2)
这样把0 , 1的数目求出来。
显然有
a01<a00∗a11
以及
a00+a01+a10+a11=C(num,2)
。
然后先初始化一个序列 , 把0放左边 , 1放右边 , 这时a10 = 0。
你可以
- 1、将最右边的0和最右边的1交换, a10=a10+num[1]
- 2、将最右边的0和它右边的1交换, a10=a10+1
然后乱搞就行了。
(我还搞出了一个奇奇怪怪的东西,不知道对不对 传送门http://blog.csdn.net/ceerrep/article/details/52314635 )
代码
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
long long a00,a01,a10,a11,num0,num1,num;
long double A,B,C,D,X;
short buf[1000050];
long long b10=0,r0,r1;
long long Calc(long long In)
{
long long ans;
A=1,B=-1,C=-In*2;
D = B * B - 4 * A * C;
if(D < 0) throw(0);
X=( sqrt(D)-B )/(2*A);
ans=floor(X);
if(X != ans) throw(1);
return ans;
}
void Solve()
{
if(num0 * num1 < a10) throw(2);
for(int i=1;i<=num0;i++)
buf[i]=0;
for(int i=num0+1;i<=num;i++)
buf[i]=1;
r0 = num0,r1 = num;
while(b10 + num1 < a10)
{
swap(buf[r0],buf[r1]);
r0--,r1--;
b10+=num1;
}
while(b10 != a10)
{
swap(buf[r0],buf[r0+1]);
r0++;
b10++;
}
}
int main(void)
{
cin >> a00 >> a01
>> a10 >> a11;
try
{
if(!(a00 || a01 || a10 || a11))
{
cout<<0<<endl;
return 0;
}
if(a00 && !a01 && !a10 && !a11)
{
num0=Calc(a00);
for(int i=1;i<=num0;i++)
cout<<0;
cout<<endl;
return 0;
}
if(!a00 && !a01 && !a10 && a11)
{
num1=Calc(a11);
for(int i=1;i<=num1;i++)
cout<<1;
cout<<endl;
return 0;
}
num0 = Calc(a00);
num1 = Calc(a11);
num = Calc(a00+a01+a10+a11);
if(num != num1 + num0) throw(-1);
Solve();
for(int i=1;i<=num;i++)
cout<<buf[i];
cout<<endl;
}
catch(int i)
{
cout<<"Impossible"<<endl;
return 0;
}
return 0;
}
友情提醒:
记得特判 (0,0,0,0),(n(n−1)/2,0,0,0)和(0,0,0,n(n−1)/2)
答案分别是 0或1 , 00……0 , 11……1 。