您的位置:首页 > 其它

洛谷2000:拯救世界——题解

2018-06-14 10:01 253 查看

https://www.luogu.org/problemnew/show/P2000

题太长了自己看吧orz……

看到这么多的限制条件,以及最后求方案数,很容易想到生成函数。

生成函数的讲解就请百度吧……以及下面公式的推导也不再阐述。

那我们就细致地列一下吧,从第一条限制到第十条限制依次如下:

\(1+x^6+x^{12}+\cdots=\frac{1}{1-x^6}\)

\(1+x+x^2+\cdots+x^9=\frac{1-x^{10}}{1-x}\)

\(1+x+x^2+\cdots+x^5=\frac{1-x^{6}}{1-x}\)

\(1+x^4+x^8+\cdots=\frac{1}{1-x^4}\)

\(1+x+x^2+\cdots+x^7=\frac{1-x^{8}}{1-x}\)

\(1+x^2+x^4+\cdots=\frac{1}{1-x^2}\)

\(1+x=\frac{1-x^{2}}{1-x}\)

\(1+x^8+x^{16}+\cdots=\frac{1}{1-x^8}\)

\(1+x^{10}+x^{20}+\cdots=\frac{1}{1-x^{10}}\)

\(1+x+x^2+x^3=\frac{1-x^{4}}{1-x}\)

接下来要做的就是把它们乘起来,得到\(\frac{1}{(1-x)^5}\)

将它展开成生成函数,则第\(n\)项系数,也就是答案,即为\(C_{n+5-1}^{5-1}=C_{n+4}^4\)高精度求出即可。

#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef double dl;
const int N=2e6+5;
const dl pi=acos(-1.0);
struct complex{
dl x,y;
complex(dl xx=0,dl yy=0){x=xx;y=yy;}
complex operator +(const complex &b)const{
return complex(x+b.x,y+b.y);
}
complex operator -(const complex &b)const{
return complex(x-b.x,y-b.y);
}
complex operator *(const complex &b)const{
return complex(x*b.x-y*b.y,x*b.y+y*b.x);
}
};
void FFT(complex a[],int n,int on){
for(int i=1,j=n>>1;i<n-1;i++){
if(i<j)swap(a[i],a[j]);
int k=n>>1;
while(j>=k){j-=k;k>>=1;}
if(j<k)j+=k;
}
for(int i=2;i<=n;i<<=1){
complex res(cos(-2*pi*on/i),sin(-2*pi*on/i));
for(int j=0;j<n;j+=i){
complex w(1,0);
for(int k=j;k<j+i/2;k++){
complex u=a[k],t=w*a[k+i/2];
a[k]=u+t;a[k+i/2]=u-t;
w=w*res;
}
}
}
if(on==-1)
for(int i=0;i<n;i++)a[i].x/=n;
}
struct Bignum{//必须定义在main之外
int a
,len;
void clear(){
memset(a,0,sizeof(a));len=0;
}
void read(){
static char s
;
scanf("%s",s);
len=strlen(s);
for(int i=0;i<len;i++)a[len-i-1]=s[i]-'0';
}
void print(){
for(int i=len-1;i>=0;i--)putchar(a[i]+'0');
putchar('\n');
}
Bignum operator +(const int &b)const{
Bignum ans;ans.clear();ans.len=len;
for(int i=0;i<ans.len;i++)ans.a[i]=a[i];
ans.a[0]+=b;
for(int i=0;i<ans.len;i++){
if(ans.a[i]>9){
ans.a[i]-=10;ans.a[i+1]++;
if(i+1==ans.len)ans.len++;
}
}
return ans;
}
Bignum operator *(const Bignum &b)const{
Bignum ans;ans.clear();ans.len=len+b.len;
int n=1;
while(n<ans.len)n<<=1;

static complex c
,d
;
for(int i=0;i<len;i++)c[i]=complex(a[i],0);
for(int i=len;i<n;i++)c[i]=complex(0,0);

for(int i=0;i<b.len;i++)d[i]=complex(b.a[i],0);
for(int i=b.len;i<n;i++)d[i]=complex(0,0);

FFT(c,n,1);FFT(d,n,1);
for(int i=0;i<n;i++)c[i]=c[i]*d[i];
FFT(c,n,-1);
for(int i=0;i<n;i++)ans.a[i]=(int)(c[i].x+0.5);
for(int i=0;i<n;i++){
ans.a[i+1]+=ans.a[i]/10;ans.a[i]%=10;
}
while(ans.a[ans.len-1]<=0&&ans.len>1)ans.len--;
return ans;
}
Bignum operator /(const int &b)const{
Bignum ans;ans.clear();
int e=0;
for(int i=len-1;i>=0;i--){
e*=10;e+=a[i];
if(e>=b){
ans.a[ans.len++]=e/b;e%=b;
}else if(ans.len){
ans.a[ans.len++]=0;
}
}
if(!ans.len)ans.a[ans.len++]=0;
for(int i=0,j=ans.len-1;i<j;i++,j--)swap(ans.a[i],ans.a[j]);
return ans;
}
}n,n1,n2,n3,n4,m;
int main(){
n.read();
n1=n+1;n2=n1+1;n3=n2+1;n4=n3+1;
n2=n2*n1;n3=n3*n2;n4=n4*n3;n4=n4/24;
n4.print();
return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +

+++++++++++++++++++++++++++++++++++++++++++

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: