数学U82394 SZYの図の三分の

トピックの背景

手にSZYプレイ三分のマップ。

タイトル説明

SZYは偉大な夢を持って、それが世界のために橋を構築することです。SZYは技術をリードするブリッジに訓練を受け、彼女が列島に来ました。

図第三の島は3つの部分A、B、Cに分割されます。彼女は設計図で可能なシナリオを計算し、それらの間のブリッジを構築したいと考えています。しかしSZYは、あまりにも多くのプログラムを感じ、そして私は彼女を助けるためにあなたを求めるだろう。要求されたプログラム番号の結果が998244353を法。

(トライマップは:頂点Vが最短と任意の2点のセットと3つの異なるポストのサブセット(A、B、C)に分割することができる場合うG =(V、E)は、無向グラフです。長さ以上3、図中の設定点Gと呼ばれる、B、図の第3の構成Cによります。)

入力形式

三つの整数、B、Cの3つの部分の数の行はA、B、Cの島です。

出力フォーマット

ライン出力は、プログラムの合計数を示します。

サンプル入力と出力

入力#1

1 1 1

出力#1

8

入力#2

1 2 2

出力#2

63

入力#3

6 2 9

出力#3

813023575

説明/ヒント

データの20%を、B、C <= 4。

;データの50%が、A、B、C <= 3000

1 <= A、B、C <= 500000データの100%まで。

問題の解決策

まず、簡単な結論:セットA、B、Cの3組の二つの各セット(例えば、a、b)はプログラムget_sumの合計(A、B)。

乗算の原則に従えば、答えは(a、b)は* get_sum(C)* get_sum(B、C)get_sumです。

我々は2つのセットのそれぞれとの間の関係を議論することができます。

2> = 3の各セット、点の集合の最小距離ので、各セットは、唯一の他の一の側に接続することができるように。

DPた場合は、その後--MLE〜は、私はエッジを見ても、答えるために直接貢献を考えます

Cは組み合わせの数であり、Aは、順列の数です。

I == 0、ANS0 = C(N、0)* A(M、0);

I == 1、ANS1 = C(N、1)* A(M、1)。

\(\シム\シム\シム\シム\シム\シム\シム\シム\シム\シム\シム\シム\シム\シム\シム\シム\シム\)

I ==分(n、m)は、ans_min(N、M)= C(N、分(N、M))* A(M、分(N、M))。

则get_sum(N、M)= ANS0 + ANS1 +···+ ans_min(N、M)。

O(n)の前階乗、フェルマーの小定理を反転さ(998244353個の素数)。

その上に。

コード:

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
const int mod = 998244353;
int read() {
    int x = 0, f = 1; char ch = getchar();
    while(! isdigit(ch)) f = (ch=='-')?-1:1, ch = getchar();
    while(isdigit(ch)) x = (x<<3)+(x<<1)+(ch^48), ch = getchar();
    return x * f;
}
int t, a, b, c, ans, ans1, ans2, ans3, fac[500005];
LL ksm(LL x, LL y) {
    LL res = 1;
    for( ; y ;x = (LL)x * x % mod, y >>= 1) 
        if(y & 1) res = (LL)res * x % mod;
    return res;
}
int C(int n, int m) { return ((LL)fac[n] * ksm(fac[n-m], mod-2))% mod  * ksm(fac[m], mod-2) % mod; }
int A(int n, int m) { return (LL)fac[n] * ksm(fac[n-m], mod-2) % mod ; }
inline int getsum(int x, int y) {
    int minl = min(x, y), ans = 0;
    for(int i = 0;i <= minl;i ++) 
        (ans += (LL)C(x, i) * A(y, i) % mod) %= mod;
    return ans;
}
int main() {
    fac[0] = fac[1] = 1;
    for(int i = 2;i <= 500000;i ++) fac[i] = (LL)fac[i-1] * i % mod;
    a = read(); b = read(); c = read();
    ans1 = getsum(a, b);
    ans2 = getsum(b, c);
    ans3 = getsum(a, c);
    ans = (((LL)ans1 * ans2) % mod) * ans3 % mod;
    printf("%d\n", ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/Paranoid-LS/p/11330847.html