イブLOJの#6358(組み合わせ、および除外をカウント)

トピックリンク

https://loj.ac/problem/6358

問題の意味

書かれた質問は、私はそれを繰り返すだろう、と同様に、Xの塊のような表面。
そこ\(N- \)から、セットを構成する要素\(2 ^ N \)サブセットは、そのようなポストのサイズの数に選択される\(4 \)倍数。数え投票しないクロスは空です。
サンプルの説明:そこは空集合から選択され、\(8 \)プログラムの種類は、空集合のみプログラムから選択されていない(\ \ {1 \} \ {2 \} \)\(\ {1 \} \ {2 \} \ {1,2 \} \) 全く何の合計がない\(11 \)種が。

問題の解決策

この質問は本当に私は不滅だった唖然。

第1単純包含および除外を検討:オーダー\(F(K)\)を表しインペリアル\(K \)番目の要素セットは、すべての選択されたプロモーターに存在しなければならない、\(F(k)は、= { N Kを選択\} (2 ^ {2 ^ {NK}} - 。1)\)
ための\(G(k)は\)正確の交点表す(K \)\のプログラムの数を、ある= \ \(F(k)の和^は{N} _ {i = K } G(k)は、G(K)= \和^ {N} _ {i = K}(-1)^ {IK} {kは{K \ Iを選択} \ Iを選択F.}(K)\)
ので、必要とされる\(N_ ^ K \当量のANS = \ {SUM 0(\ MOD 4)} G(K)\)

高エネルギーフロント-
私たちは、係数の構造を検討し、\を(\アルファ(I)\) (?問題への公式ソリューションは、「封入排除要因」と呼んだが、私はそれを見つけられませんでしたし、及び除外の関係はどのようなものです)だから\(ANS = \ SUM ^ {N-} _ {i = 0} F(I)\アルファ(I)\)
まったく存在しない場合\(Kが\)されている\(4 \)この状態の複数、全て\(K \)加算、次いで撥容量式に従ってこと導入することができる\(\アルファ(I)= [I = 0] \) の目的を達成します。
さて、この状態で、私達はちょうど私たちがやっているという事実を考慮してください
するために\(G(N)\) である\(F(K)\)で計算される(nは\ k個\選択)\回。時間は、我々は、総計算が必要\(1 \)回、それは\ [\ N FORALL、\和 ^ {N} _ {K = 0} {N \ Kを選択} \アルファ(K)= 1 \] 採取\(\アルファ(K)= [K = 0] \) 今はれるに\(\ nはFORALL、\和 ^ {N} _ {K = 0} {N \ Kを選択} \アルファ(K)= K \当量0(\ MOD 4)] \) 二項反転があるので\(F(N)= \和^ {N} _ {K = 0}(-1)^ {NK} {N \選択K} [K \当量0(\ MOD 4)] \)

このことは、どれだけ速く、需要のですか?単位根を-数論が得られなければならない品物のタイトルを殺すために道を取りました!オーダー\(M = 4 \) \(\オメガ\)\(4 \)ビュー(メイン)単位根がある\ [[N \当量0( \ MOD M)] = \ FRAC {1} { N} \和^ {M-
1} _ {i = 0} \オメガ^ {}内の\] そう\(\アルファ(N)= \ FRAC {1} {M} \和^ {N} _ {K = 0}( - 1)^ {NK} {N \選択K} \和^ {M-1} _ {i = 0}(\オメガ^ I)は、k = \和^ {M-1} _ {I = 0}(\オメガ^ I
-1)^ k個の\) を直接計算することができます。

時間複雑\(O(nm)を\)

黙示録:でも、最近作られた2つの質問の妖精構築し、多くの場合、いくつかの遷移行列/および除外係数のもので構成は、/再帰的に目的を達成したい、思考のこのラインは、学習の価値があります。

コード

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cassert>
#include<iostream>
#define llong long long
using namespace std;

inline int read()
{
    int x=0; bool f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
    for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
    if(f) return x;
    return -x;
}

const int N = 1e7;
const int P = 998244353;
const llong G = 3ll;
const llong W = 911660635ll;
const llong INV4 = 748683265ll;

int fact[N+3],finv[N+3];
llong f[N+3],a[N+3];
int n;

llong quickpow(llong x,llong y)
{
    llong cur = x,ret = 1ll;
    for(int i=0; y; i++)
    {
        if(y&(1ll<<i)) {y-=(1ll<<i); ret = ret*cur%P;}
        cur = cur*cur%P;
    }
    return ret;
}
llong comb(llong x,llong y) {return x<0||y<0||x<y ? 0ll : (llong)fact[x]*(llong)finv[y]%P*(llong)finv[x-y]%P;}

int main()
{
    fact[0] = 1ll; for(int i=1; i<=N; i++) fact[i] = (llong)fact[i-1]*i%P;
    finv[N] = quickpow(fact[N],P-2); for(int i=N-1; i>=0; i--) finv[i] = (llong)finv[i+1]*(i+1ll)%P;
    scanf("%d",&n);
    f[n] = 2ll; for(int i=n-1; i>=0; i--) f[i] = f[i+1]*f[i+1]%P;
    for(int i=0; i<=n; i++) f[i]--;
    for(int i=0; i<=n; i++) f[i] = f[i]*comb(n,i)%P;
    for(int i=0; i<4; i++)
    {
        llong tmp = 1ll,expn = quickpow(W,i);
        for(int j=0; j<=n; j++)
        {
            a[j] = (a[j]+tmp)%P;
            tmp = tmp*(expn-1ll)%P;
        }
    }
    for(int i=0; i<=n; i++) a[i] = a[i]*INV4%P;
//  for(int i=0; i<=n; i++) printf("%lld ",a[i]); puts("");
    llong ans = 1ll;
    for(int i=0; i<=n; i++) ans = (ans+f[i]*a[i])%P;
    printf("%lld\n",ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/suncongbo/p/11275081.html