ベルヌーイ数(インデックス生成機能)
我々は異なるアルゴリズムのために他の計算を使用する場合は、\(のt \)自然数のパワーと多項式、その後、一枚の紙は、実際には、いくつかのプロパティは、(ここに来て記載されていない)を観察することができます。ヤコブベルヌーイは、法律の一つを発見しました...
:便宜のために、我々は我々の表記変更\(。S_T(N)= \ sum_ I = {0} 1} ^ {N-I-T ^を\) 。私たちは、(N ^トンの\)は\削除します。それは私たちがセクションのスターリング数で行ったよう、以下の分析により便利に、そしてほとんど影響を持っています。
ベルヌーイ結果は:
\ [S_T(N)= \ {FRAC 1 1} + {T} \ sum_ I = {0} T ^ {} \ Binom {T} + I {B_i 1} ^ {N-T + 1-iが} \]
ここで、\(B_i \)ベルヌーイの数です。私たちは、この式は最初にそれが何であるか、使用を見てみましょう、先送りに証明します。
注意その場合\(N = 1 \) 、場合\(S_T(n-は)\)となる\(0 ^ Tの\)を、これだけ\(T = 0 \)それは(1 \を\ )、他の回はしている)0 \(\します。この時点でなお、我々は、ベルヌーイの側面を含む式を得る:
。\ [\ sum_ I = {0} T ^ {} \ Binom {T} + {I} B_i 1 = 0、T> 0 \]
場合は\(T = 0 \) 、我々は得ることができます\(= B_0。1 \) 。今、私たちは再帰することができます\(B_T \) 、および再帰的な複雑さを得るためにキーをシフトです\()O(T ^ 2 \) です。
\ [B_T = - \ FRAC {
1}、{T + 1} \ sum_ {i = 0} ^ {T-1} \ {T + 1} {} B_i \はbinom] またベルヌーイが得上述結論ダイレクトフォームは多項式であるので、ベルヌーイ多項式の数によって得られる\(O(T)\) 、これらの方法の最速です。
次に我々はこの事は、誘導によって証明することができます...この事を証明する必要があるが、それは非常に複雑な暴力に見える...幸いなことに、指数関数を生成する方法があります。
列の数\(F_n \)指数生成関数は、$ \ハットF(Z)=であり、 \ sum_ {N \ GEQ 0} f_nの\のFRAC {Z ^ n}は{N!} $。
私たちは、指数生成機能を乗算によって生成された2つの指数関数を置くのであれば、その2つの指数生成関数の畳み込みによって得られます。例えば、のための\(\帽子F(Z)\ハットG(Z)= \ハットH(Z)\):\
[H_n = \ sum_ {I = 0} ^ {N-} \ Binom {N-} {I} F_iとG_ {NI} \]
我々は再帰式を使用して指数関数を生成するために始めることができます。私たちは使用(N- \)\の代わりに\(1 + T \) 、次いで両側プラス\(B_N \)を得た
\ [\ sum_ {i = 0 } ^ {N} \ binom {N } {I} = B_i B_N、N> 1 \]
実際には、左側である(\ \ハットB(Z) \) 全ての係数\(1 \)インデックス生成関数内の列の数(\(E ^ Z \) 2畳み込み)は、我々が作る(\をN = 1 \)場合、ケースが右側よりなり\(1 \) 。そう
\ [\帽子B(Z) E ^ Z = \帽子B(Z)+ Zの\]
変形を得ることができる\(\帽子B(Z)= \ Z FRAC {} {} 1-E ^ Z \)指数ベルヌーイ生成関数の数です。(これは、逆多項式のFFTにより得られる\(O(T \ログT )\) の前処理ベルヌーイ数の方法)
次に、考える\(T \)の電力をして。私たちは、指数生成機能みなと使用しようとしました\(T \)の電力をして。正常な機能は、我々は分母に乗る等差数列を生成することであるため、数だけ和解の形で記述することができ、それは特に意味がありません。指数生成機能、我々はあなたが単純化することができ、等比級数で、その結果、算術シーケンスインデックスに移動していると思っています。
\ [E ^ {KZ} = \ sum_ iはFRAC {Z ^ Iを} \ ^ K {iは0をGEQ \} {I!} \]
これは列の数である\(K ^ 0、K ^ 1、K ^ 2、\ cdots \) 、我々は限り、我々は、自然数のパワーを主張もしそうであれば、指数生成機能(0 \)\に\(N-1 \)\(E ^ {KZ} \ ) :追加する
。\ [\ sum_ ^ {K} = {0} 1-N-KZ} = E {^ \ FRAC {E ^ {-1}、{E} NZ ^ Z-を1} \]
これは、単純な形でした。接触ベルヌーイ数単独関数生成:
\ [\ハットS_T(Z)= \ハットB(Z)\ FRAC E ^ {-1} {} {NZ Z} \]
右側のと同様の2に変換することができ2つの畳み込み番号列の形、しかしで、少し異なる場合\(\ FRAC {E ^ { NZ} -1}、{Z} \) 実際には、\(N ^ 0、N ^ 1、N ^ 2 、\ cdots \)定数項を削除し、生成関数の通常の意味の一方を移動させる機能を生成します。これは、その奇妙な内部の二項係数式につながる\(+ 1 \) 。展開し、当社の式aです。
[TJOI2018]教科書の冒涜
ゲームをプレイしたい、そして今、彼はゲームをプレイしたことは、このような場面に遭遇し、すべての奇妙な血液がされアズキ(\ a_iをを)\、各モンスターの血が、張小豆無制限の手と同じではありません「冒涜。」効果は、すべての奇妙なの冒涜によって引き起こされる\(1 \)損傷、奇妙な死がある場合は、再び呪文を唱えます。私たちは、血液があると信じています\(0 \)モンスター死。
「冒涜」を用い小豆は、特定のスコアを取得し、スコアがその各々は奇妙害が生成する冒涜であり、「冒涜」を使用した後、次のように計算される\(X- ^ k個の\) 、\(Xの\)を損傷が原因とされる前に、血液を非難する\(X \)必要部数と全てのモンスターの「冒涜」殺すために必要\(k個の\を)。
最終的な出力は、小豆スコアを得ることができる\(\ ^ 10 MOD。7. 9 + \) 。
[入力形式
最初の行動のテストデータの各セット\(N、M \) 、最高電流血液モンスター表現\(N-を\) 、および\(m個\)血液中に現れない種。
次\(m個\)行、各行\(1 \)数\(a_iを\)は、血液のフィールドを示すことはされていない(a_iを\)\モンスター。
[データ]の範囲
のための\(100 \%\)データ、\は、(N- \ル^ {10} 13、M \ル50 \です)。
問題の解決策
数のすべての必要なモンスター「冒涜」殺すことが必要であるので、各ない血液は、「冒涜」によって中断されません\(K = M + 1 \)を。
そして、それぞれの貢献は自然数と消費電力である - パワーとフォームの数、それは問題に形質転換し、自然数のパワーを見つけます。
ベルヌーイ数、時間複雑度を有する溶液\(O(M ^ 2)\) 。
#include<bits/stdc++.h>
#define co const
#define il inline
template<class T> T read(){
T x=0,w=1;char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-') w=-w;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*w;
}
template<class T>il T read(T&x){
return x=read<T>();
}
using namespace std;
typedef long long LL;
co int mod=1000000000+7;
il int add(int a,int b){
return (a+=b)>=mod?a-mod:a;
}
il int mul(int a,int b){
return (LL)a*b%mod;
}
il int fpow(int a,int b){
int ans=1;
for(;b;b>>=1,a=mul(a,a))
if(b&1) ans=mul(ans,a);
return ans;
}
co int N=60;
LL n,a[N];
int m,b[N],c[N][N],inv[N];
int calc(LL n){
int ans=0;
for(int i=1;i<=m+1;++i)
ans=add(ans,mul(c[m+1][i],mul(b[m+1-i],fpow((n+1)%mod,i))));
ans=mul(ans,inv[m+1]);
return ans;
}
void real_main(){
read(n),read(m);
for(int i=1;i<=m;++i) read(a[i]);
a[++m]=++n;
sort(a+1,a+m+1);
int ans=0;
for(int i=1;i<=m;++i){
for(int j=i;j<=m;++j)
ans=add(ans,add(calc(a[j]-1),mod-calc(a[j-1])));
for(int j=i+1;j<=m;++j) a[j]-=a[i];
a[i]=0;
}
printf("%d\n",ans);
}
int main(){
inv[0]=inv[1]=1;
for(int i=2;i<=55;++i) inv[i]=mul(mod-mod/i,inv[mod%i]);
for(int i=0;i<=55;++i){
c[i][0]=c[i][i]=1;
for(int j=1;j<i;++j) c[i][j]=add(c[i-1][j-1],c[i-1][j]);
}
b[0]=1;
for(int i=1;i<=55;++i){
for(int j=0;j<i;++j) b[i]=add(b[i],mul(c[i+1][j],b[j]));
b[i]=mul(mod-b[i],inv[i+1]);
}
for(int t=read<int>();t--;) real_main();
return 0;
}