D.サンタさんのボット

質問の意味:サンタクロースは今年、もちろん、サンタクロースからのいくつかの贈り物を取得したいすべての子供は、特に、i番目のKIの子供たちが中に別の贈り物をしたいということからの手紙n個の異なる子どもの数を受け取りました彼の贈り物として、いくつかの贈り物は、複数の子を持つことができます。

サンタクロースは、彼が、残念ながら、子供たちにいくつかの贈り物を選択し、ロボットアルゴリズムいくつかのバグ、子供たちにいくつかの贈り物を選択するための新しいロボットを望んでいるので、ロボットが次のアクションを実行し、非常に忙しいです:
nは1等しい確率子供たちは子供たちを選んX
2 X KXギフト中等度の確率はyの贈り物に選任されたい子から
このギフトzを受け入れるように子供を選択する3.等しい確率を
(xは、Y、X)が呼ばれるロボット選択肢は
存在ギフトのy zが記載されている子供がある場合、そのオプションは有効です。
効果的な選択する確率を計算

入力:
最初の行は、n番目の子を示し
、i番目の行は、クリスマスのプレゼントのリストを表し、次のn行をi番目の子は、KI、AI1、AI2、...望んで AIKI、
表示されません同じリストで贈り物を繰り返し

出力:
確率印刷ロボット有効な選択肢、この確率は既約分数として表現される(\ \ FRAC {X}、{Y} \) あなたが印刷する必要があり、\(X \ CDOT {Y} ^ { - 1} \ 998244353 MOD)

分析:タイトル手段のn子供があるということです、それぞれの子はギフト気を持っているが、彼らが望むもので、今でランダムにこのギフトを受け入れるために子供を迎え、この贈り物は、彼が単一で存在したいの贈り物です。確率はお問い合わせ
、我々は今の子のxを選ぶと仮定し、彼は確率が1 / nは、確率は1 / N * 1 / Kになり、彼の希望リストからの贈り物を選ぶ白羽[ x]は、 その後、ピックアップ子供との確率で行中:1 / N- * 1 / K [X-] *数(すべての希望リスト内)/ nのギフトのは、あなたがこの確率得ることができ
、出力を既約にこの確率を置くために私たちを必要とし次いで、フラクションX / Y、998244353 X / Y MOD見つけ、この効果は、高速電力素子は、* Xのこの形態にX / Y MOD PものであるQ MOD P、逆高速電力反転さを採用することができますこの乗算に分割し、それら相模値が等しいことを
コンピュータ部門でもたくさんのに変わるとなり、乗算、ので、
高速で電源を法:このようなものの数論で、この質問を理解したいの知識を付ける必要があります高速電力反転元

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;

using LL = long long;
const int mod = 998244353;
const int N = 1e6 + 5;
vector<int> list[N];
int k[N];
//记录礼物数量
int cnt[N];
//快速模
LL qmi(int a, int b, int p)
{
    LL res = 1;
    while (b)
    {
        if (b & 1) res = res * a % p;
        a = a * (LL)a % p;
        b >>= 1;//b右移一位
    }
    return res;
}

//费马小定理
//y的模mod的乘法逆元
int Fermat(int y)
{
    return qmi(y, mod - 2, mod);
}

int main()
{
    //n个小孩
    int n;
    scanf("%d", &n);

    for (int i = 1; i <= n; ++i)
    {
        scanf("%d", &k[i]);
        list[i].resize(k[i] + 1);
        for (int j = 1; j <= k[i]; ++j)
        {
            scanf("%d", &list[i][j]);
            ++cnt[list[i][j]];
        }
    }

    LL res = 0;
    //计算概率

    //只需求1/k[x] * cnt即可
    for (int i = 1; i <= n; ++i)
    {
        LL cur = 0;
        for (int j = 1; j <= k[i]; ++j)
            cur += cnt[list[i][j]];
        //求k[i]模mod的乘法逆元
        res += ((cur % mod) * Fermat(k[i])) % mod;
    }
    //再乘以1 / n * n
    res = ((res % mod)) * Fermat((1ll * n * n) % mod) % mod;

    printf("%lld\n", res);


    return 0;
}

おすすめ

転載: www.cnblogs.com/pixel-Teee/p/12127496.html