题目大意:给定一个含有n个变量的2^n项的多项式,将每个变量分别选-1和1代入求值,求多项式的各项系数
《论一道题究竟如何出才能同时卡时间卡内存卡精度卡输入卡输出卡评测》
很久之前盯着这道题看了很长时间……直到今天我才发现这题原来是道傻逼题。。。
我们用三个变量举例
假设f(x)=a0x1x2x3+a1x1x2+a2x1x3+a3x2x3+a4x1+a5x2+a6x3+a7
那么我们把含有x1的项提出来 得到
f(x)=x1(a0x2x3+a1x2+a2x3+a4)+(a3x2x3+a5x2+a6x3+a7)
然后我们把x1=1和x1=-1分别带进去,两个式子加一下除以2,加号的左边“Duang”地一下就没啦!
然后我们把x1=1和x1=-1分别带进去,两个式子减一下除以2,加号的右边“Duang”地一下也没啦!
然后。。。。然后。。。然后没有然后辣。。。递归做到底就是了。。。
于是这题考的实际上是如何处理题目中遇到的各种恶心情况?
果断BZ倒数第一,第十个点本机跑了9s+,于是我其实根本不算AC掉这题了?
最后一个点输出46MB真是吓死爹了
留念= =
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define EPS 1e-7
using namespace std;
struct OStream{
#define L (1<<20)
char buffer[L],*S;
OStream()
{
S=buffer;
}
void Putchar(char c)
{
*S++=c;
if(S==buffer+L)
{
fwrite(buffer,1,L,stdout);
S=buffer;
}
}
void Print(int x)
{
static int stack[20],top;
if(x<0)
Putchar('-'),x=-x;
if(x==0)
Putchar('0');
while(x)
stack[++top]=x%10,x/=10;
while(top)
Putchar(stack[top--]+'0');
}
~OStream()
{
fwrite(buffer,1,S-buffer,stdout);
}
}os;
struct Frac{
int a,b;
Frac() {}
Frac(long long _,long long __=1)
{
int gcd=__gcd(_,__);
a=_/gcd;
b=__/gcd;
if(b<0) a=-a,b=-b;
}
friend istream& operator >> (istream &_,Frac &x)
{
double a;
scanf("%lf",&a);
x=Frac((long long)(a*100+(a<0?-EPS:EPS)),100);
return _;
}
friend Frac operator + (const Frac &x,const Frac &y)
{
int gcd=__gcd(x.b,y.b),lcm=x.b/gcd*y.b;
Frac re((long long)x.a*(lcm/x.b)+(long long)y.a*(lcm/y.b),lcm);
return re;
}
friend Frac operator - (const Frac &x,const Frac &y)
{
int gcd=__gcd(x.b,y.b),lcm=x.b/gcd*y.b;
Frac re((long long)x.a*(lcm/x.b)-(long long)y.a*(lcm/y.b),lcm);
return re;
}
friend Frac operator / (const Frac &x,int y)
{
Frac re(x.a,x.b*y);
return re;
}
friend ostream& operator << (ostream &_,const Frac &x)
{
if(x.b==1)
os.Print(x.a);
else
os.Print(x.a),os.Putchar('/'),os.Print(x.b);
return _;
}
};
int n;
struct abcd{
int sta;
Frac val;
friend istream& operator >> (istream &_,abcd &a)
{
int i;
static char s[30];
scanf("%s",s+1);
for(i=1;i<=n;i++)
(a.sta<<=1)|=(s[i]=='+'?1:0);
cin>>a.val;
return _;
}
bool operator < (const abcd &a) const
{
return sta > a.sta;
}
}a[1<<20];
//我真是日了我家那只萌萌哒的POI了= =
void Divide_And_Conquer(abcd a[],int n)
{
int i;
if(n==1) return ;
abcd *l=a,*r=a+(n>>1);
for(i=0;i<n>>1;i++)
{
Frac x=l[i].val,y=r[i].val;
l[i].val=(x-y)/2;
r[i].val=(x+y)/2;
}
Divide_And_Conquer(l,n>>1);
Divide_And_Conquer(r,n>>1);
abcd C=a[n>>1];
for(i=n>>1;i;i--)
a[i]=a[i-1];
a[0]=C;
}
int main()
{
int i,j;
cin>>n;
for(i=0;i<1<<n;i++)
cin>>a[i];
sort(a,a+(1<<n));
Divide_And_Conquer(a,1<<n);
for(i=0;i<1<<n;i++)
{
if(!a[i].val.a)
continue;
cout<<a[i].val;
if(i) os.Putchar(' ');
for(j=1;j<=n;j++)
if(a[i].sta&(1<<n-j))
os.Putchar('x'),os.Print(j);
os.Putchar('\n');
}
return 0;
}