6300カウント

説明

OJを参照してください。

溶液

問題の最初の外観は、我々が見つかりました(\ \ {A [I] N-} = SUM \)ので、問題が引出しとして理解することができます。
しかし、それだけではないですが限界があり、\(N \)はまた、非常に大きいです。どのようにそれを行うには?
%%% %%%は兄が考えられるSLS (\和{[I \ \]}) に分解(\ \和{B [I ] * M + P [I]}(P [i]は< M)\)
とするための\(B [i]が\) 次いで、組合せの数によって直接決定することができる\(P [I] \)次に?
私たちは、いくつかの式を見てみましょう:
\(\ {P SUM [I]}≡N(MODのM)\)
\(。\ {P SUM [I]} <= K *(M - 1)\)
我々列挙することができる(\ \ {P SUM [I]を} \)
単語の組み合わせのいくつかの数の直接使用ただし、\(Pの[私] \)超えてもよい\を(M - 1 \)ので、我々は、包含および除外を使用する必要があります。
私たちは、数の数(設定列挙してみましょう\(J \) を超える\(1-Mの\) その後、最初の\を(\和{P [I ]} \) 減算\(J *を(M -1)\)
そして、それはあなたがそれを元に戻すことができます任意の数の組み合わせを見つけます。最後に、忘れてはいけません\(B [i]が\)の組み合わせの数を。

コード

#include <cstdio>
#define N 5010
#define maxn 10000000 
#define ll long long
#define mo 998244353
#define mem(x, a) memset(x, a, sizeof x)
#define fo(x, a, b) for (int x = a; x <= b; x++)
#define fd(x, a, b) for (int x = a; x >= b; x--)
using namespace std;
int m, K, nmm;
ll n, ans = 0, s;
ll jc[maxn + 10], ny[maxn + 10];

ll ksm(ll x, int y)
{
    ll s = 1;
    while (y)
    {
        if (y & 1) s = s * x % mo;
        x = x * x % mo; y >>= 1;
    }
    return s;
}

ll C(int x, int y) {return x > y ? 0 : jc[y] * ny[x] % mo * ny[y - x] % mo;}

ll calc(ll x, ll y)
{
    if (x > y) return 0;
    ll s = 1;
    for (ll i = y - x + 1; i <= y; i++) s = s * (i % mo) % mo;
    s = s * ny[x] % mo;
    return s;
}

int main()
{
    freopen("count.in", "r", stdin);
    freopen("count.out", "w", stdout);
    scanf("%lld%d%d", &n, &m, &K); nmm = n % m;
    if (m == 1) {puts("0"); return 0;}
    if (K == 1) {printf("%d\n", n % m == 0 ? 0 : 1); return 0;}
    jc[0] = ny[0] = 1;
    fo(i, 1, maxn) jc[i] = jc[i - 1] * i % mo;
    ny[maxn] = ksm(jc[maxn], mo - 2);
    fd(i, maxn - 1, 1) ny[i] = ny[i + 1] * (i + 1) % mo;
    for (ll sump = nmm; sump <= K * (m - 1); sump += m)
    {
        s = 0;
        fo(i, 0, K)
        {
//          printf("%lld %lld\n", K - 1, sump - i * (m - 1) - 1);
            s = (s + C(K - 1, sump - i * (m - 1) - 1) * C(i, K) % mo * ((i & 1) ? -1 : 1)) % mo;
        }
//      printf("%lld %lld\n", sump, s);
        ans = (ans + s * calc(K - 1, K + (n - sump) / m - 1) % mo) % mo;
//      printf("%lld\n", ans);
    }
    printf("%lld\n", (ans + mo) % mo);
    return 0;
}

おすすめ

転載: www.cnblogs.com/jz929/p/11348629.html