AtCoder AGC036C GP 2 (组合计数)

题目链接

https://atcoder.jp/contests/agc036/tasks/agc036_c

题解

终于有时间补agc036的题了。
这题其实不难的来着……我太菜了考场上没想出来

首先转化一下题目: 一个序列可以被按题目的操作方式生成当且仅当它长度为\(N\), 总和为\(3M\), 且最大数不超过\(2M\), 奇数的个数不超过\(M\).
必要性显然,充分性归纳易证。

然后考虑怎么计数: 先不考虑第二个条件,定义\(f(n,m,k)\)表示长度为\(n\)总和为\(m\)奇数不超过\(k\)个的方案数,那么枚举奇数的个数\(i\), 剩下的偶数和为\(m-1\), 有\(f(n,m,k)=\sum^{k}_{i\equiv m(\mod 2)}{n\choose i}{\frac{m-i}{2}+n-1\choose n-1}\).
考虑第二个条件,补集转化,最大数大于\(2M\)意味着剩下的所有数和小于\(M\), 那么不要把和式写出来然后无脑推式子!固定下最大的数的位置\(1\),给第一个数减去\(2M\) (这是个偶数所以不影响奇数那个条件),就是要求\(个数和为\)M$, 第一个数大于\(0\),一共有不超过\(M\)个奇数的方案数。这个因为有奇数个数的限制所以枚举很麻烦,那就再补集转化!转化为\((N-1)\)个数和为\(M\)且奇数不超过\(M\)个。

因此最后答案就是\(f(N,3M,M)-N(f(N,M,M)-f(N-1,M,M))\).

时间复杂度\(O(N+M)\).

代码

#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 = 2e6;
const int P = 998244353;
llong fact[N+3],finv[N+3];

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 : fact[x]*finv[y]%P*finv[x-y]%P;}

llong calc(llong n,llong m,llong k)
{
    llong ret = 0ll;
    for(int i=0; i<=k; i++)
    {
        if((m-i)&1) continue;
        llong tmp = comb(n,i)*comb(((m-i)>>1)+n-1,n-1)%P;
        ret = (ret+tmp)%P;
    }
//  printf("calc %lld %lld %lld=%lld\n",n,m,k,ret);
    return ret;
}

int n,m;

int main()
{
    fact[0] = 1ll; for(int i=1; i<=N; i++) fact[i] = fact[i-1]*i%P;
    finv[N] = quickpow(fact[N],P-2); for(int i=N-1; i>=0; i--) finv[i] = finv[i+1]*(i+1)%P;
    scanf("%d%d",&n,&m);
    llong ans = calc(n,3*m,m);
    ans = (ans-n*(calc(n,m,m)-calc(n-1,m,m)+P)%P+P)%P;
    printf("%lld\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/suncongbo/p/11297768.html

时间: 2024-07-30 22:22:27

AtCoder AGC036C GP 2 (组合计数)的相关文章

AtCoder AGC032F One Third (组合计数、DP、概率期望、微积分)

题目链接 https://atcoder.jp/contests/agc032/tasks/agc032_f 题解 神仙题.. 第一步转化利用了\(\frac{1}{3}\)这个数特有的性质.假设我们用红线标出每一次切割的位置,再在每一次切割的位置顺时针\(120\)度处用蓝线标出,那么答案就等于红线与蓝线之间的最小夹角.但是这样转化完了依然不好做(而且似乎也没用到\(\frac{1}{3}\)的特殊性),那么考虑如果在每一次切割的位置逆时针\(120\)度处用绿线标出,答案依然是不变的,因为\

AtCoder AGC035F Two Histograms (组合计数、容斥原理)

题目链接 https://atcoder.jp/contests/agc035/tasks/agc035_f 题解 B题难度的F题--然而我还是不会 假设第\(i\)行染的长度是\(a_i\), 第\(j\)列是\(b_j\) 考虑什么情况下两种方案会重复: 若存在\(i,j\)使得\(a_i+1=j\)且\(b_j=i\), 那么令\(a'_i=j-1,b'_j=i+1\)可以得到一样的结果. 那么我们也就是要计算不存在\(a_i+1=j\)且\(b_j=i\)的序列\(a,b\)个数. 充分

Yue Fei&#39;s Battle(组合计数递推)

//求一个直径为 k 的树有多少种形态,每个点的度不超过 3 // 非常完美的分析,学到了,就是要细细推,并且写的时候要细心 还有除法取模需要用逆元 #include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> using namespace std; #define MOD 1000000007 #define L

POJ 1496 POJ 1850 组合计数

Code Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 8256 Accepted: 3906 Description Transmitting and memorizing information is a task that requires different coding systems for the best use of the available space. A well known system is t

bzoj 1004 Cards 组合计数

这道题考察的是组合计数(用Burnside,当然也可以认为是Polya的变形,毕竟Polya是Burnside推导出来的). 这一类问题的本质是计算置换群(A,P)中不动点个数!(所谓不动点,是一个二元组(a,p),a∈A,p∈P ,使得p(a)=a,即a在置换p的作用后还是a). Polya定理其实就是告诉了我们一类问题的不动点数的计算方法. 对于Burnside定理的考察,我见过的有以下几种形式(但归根结底还是计算不动点数): 1.限制a(a∈A)的特点,本题即是如此(限制了各颜色个数,可以

POJ 3252 组合计数

Round Numbers Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9149 Accepted: 3248 Description The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, Paper, Stone' (also known as 'Rock, Paper, Scissors', 'Ro,

HDU4675-GCD of Sequence(数论+组合计数)

GCD of Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 949    Accepted Submission(s): 284 Problem Description Alice is playing a game with Bob. Alice shows N integers a1, a2, -, aN, an

[HDU 3461] Saving Beans &amp; 组合计数Lucas定理模板

Saving Beans Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description Although winter is far away, squirrels have to work day and night to save beans. They need plenty of food to get through those long cold

POJ 1019 组合计数

链接:POJ 1019 /***************************************** author : Grant Yuan time : 2014/10/19 14:38 source : POJ 1019 algorithm: 组合计数 ******************************************/ #include <iostream> #include <cstdio> #include <algorithm> #