1. 程式人生 > >BZOJ3028食物——生成函數+泰勒展開

BZOJ3028食物——生成函數+泰勒展開

namespace ret i+1 rsquo span strlen algorithm 註意 spa

題目描述

明明這次又要出去旅遊了,和上次不同的是,他這次要去宇宙探險!我們暫且不討論他有多麽NC,他又幻想了他應 該帶一些什麽東西。理所當然的,你當然要幫他計算攜帶N件物品的方案數。他這次又準備帶一些受歡迎的食物, 如:蜜桃多啦,雞塊啦,承德漢堡等等當然,他又有一些稀奇古怪的限制:每種食物的限制如下: 承德漢堡:偶數個 可樂:0個或1個 雞腿:0個,1個或2個 蜜桃多:奇數個 雞塊:4的倍數個 包子:0個,1個,2個或3個 土豆片炒肉:不超過一個。 面包:3的倍數個 註意,這裏我們懶得考慮明明對於帶的食物該怎麽搭配著吃,也認為每種食物都是以‘個’為單位(反正是幻想嘛 ),只要總數加起來是N就算一種方案。因此,對於給出的N,你需要計算出方案數,並對10007取模。

輸入

輸入一個數字N,1<=n<=10^500

輸出

如題

樣例輸入

輸入樣例1
1
輸入樣例2
5

樣例輸出

輸出樣例1
1
輸出樣例2
35
對於每種食物的限制,我們可以用多項式形式來表示,$a_{i}x^i$表示這種食物取$i$個時的方案數是$a_{i}$。 那麽對於每種食物,我們可以列出對應多項式,答案就是將所有多項式相乘後$x^n$的系數。 承德漢堡:$\sum\limits_{i=0}^{+\infty}x^{2i}=\frac{1}{1-x^2}$ 可樂:$1+x$ 雞腿:$1+x+x^2=\frac{x^3-1}{x-1}$
蜜桃多:$\sum\limits_{i=0}^{+\infty}x^{2i+1}=\frac{x}{1-x^2}$ 雞塊:$\sum\limits_{i=0}^{+\infty}x^{4i}=\frac{1}{1-x^4}$ 包子:$1+x+x^2+x^3=\frac{x^4-1}{x-1}$ 土豆片炒肉:$1+x$ 面包:$\sum\limits_{i=0}^{+\infty}x^{3i}=\frac{1}{1-x^3}$ 由等比數列求和公式即可推得等式右邊的部分,那麽將所有生成函數都乘起來就能得到:$\frac{x}{(1-x)^4}$ 根據泰勒展開可以知道$\frac{1}{(1-x)^m}=(1+x+x^2+x^3+……)^m$,求第$n$項系數就是$C_{m+n-1}^{m-1}$
乘上$x$就相當於把系數都右移一位,即求第$n-1$項系數為$C_{m+n-2}^{m-1}$,將$m=4$代入,那麽答案就是$C_{n+2}^{3}$。
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define mod 10007
using namespace std;
int ans;
int n;
char s[1000];
ll quick(int x,int y)
{
	ll res=1ll;
	while(y)
	{
		if(y&1)
		{
			res=res*x%mod;
		}
		y>>=1;
		x=1ll*x*x%mod;
	}
	return res;
}
int main()
{
	scanf("%s",s+1);
	int len=strlen(s+1);
	for(int i=1;i<=len;i++)
	{
		n=n*10+s[i]-‘0‘;
		n%=mod;
	}
	ans=n*(n+1)%mod;
	ans=ans*(n+2)%mod;
	ans=ans*quick(6,mod-2)%mod;
	ans=(ans%mod+mod)%mod;
	printf("%d",ans);
}

BZOJ3028食物——生成函數+泰勒展開