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

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[N],len;
    void clear(){
	memset(a,0,sizeof(a));len=0;
    }
    void read(){
	static char s[N];
	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[N],d[N];
	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/ +

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

posted @ 2018-06-14 10:01  luyouqi233  阅读(710)  评论(0编辑  收藏  举报