首页 > 其他分享 >P10380 「ALFR Round 1」D 小山的元力

P10380 「ALFR Round 1」D 小山的元力

时间:2024-05-25 17:22:29浏览次数:17  
标签:return int sum times 元力 阶乘 P10380 Round LL

历时两天,算是搞出来了。
P10380 「ALFR Round 1」D 小山的元力 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

提醒
首先如果你是用 Lucas 定理并用阶乘形式来求组合数的,请判断组合数是否成立,即 \(C_a^b\),\(a\) 是否大于等于 \(b\)。如果小于你将 re 几个点,如果是直接用快速幂求解逆元来做的,恭喜你,你将 WA#20和#46。因为 \(p\) 可能小于 \(n,m\) 或 \(n + m\),导致你求出的阶乘到了\(f[p]\) 时变为 \(0\),使得后面的计算错误。

正题

分析题意,首先对于第 \(i\) 堆,当这堆放这 \(k\) 个元素的时候,无论这是哪一堆,它外面的情况的总数都是一样的,也就是分配剩下 \(n - k\) 个数的情况的数量是一样的。每一堆都如此,那么这堆放 \(k\) 个元素的总贡献就是 \(k \times 总情况数 \times sum\) 。 \(sum = 1! + 2! + \dots + m!\) 因为 sum 是固定的所以可以提出来最后相乘,那么目标就是求所有的 \(k \times 总情况数\)。

设一共有 \(n\) 个相同元素,放 \(m\) 堆(每堆可以不放),\(k\in [0,n]\),那么剩下的就是求每个 \(k\) 对应的总情况数。

设当前堆放 \(k\) 个数,那么就剩下 \(n - k\) 个数要分配到 \(m - 1\) 个空堆(可以不放)。这里可以用隔板法,用 \(m - 2\) 个隔板,把剩下 \(n - k\) 个数分成 \(m - 1\) 块。因为有空堆,而隔板法不能有空的分配,所以可以人为添加 \(m - 1\) 个元素,把情况变成必须放,这时候元素有 \(n - k + m - 1\) 个,空隙(两边不算)有 \(n - k + m - 1 - 1\) 个,即 \(n - k + m - 2\) 个。剩下的就是在这 \(n - k - 2\) 个空隙里面选 \(m - 2\) 个放上隔板,也就是求 \(C_{n - k + m - 2} ^ {m - 2}\)。

求组合数有很多方法,当时看数据范围,我直接用的快速幂求通过阶乘求解,然后因为 \(p\) 的大小寄掉了,也就是上面的提醒。因此这里用 Lucas 定理求解组合数,这样就不会因为 \(p\) 的事情寄掉了,时间上也够。且因为模数 \(p\) 不变,所以可以先预处理阶乘,但是不要先预处理逆元,否则时间复杂度会变成 \(O(p\log n)\) 容易 TLE。动态求解逆元,求出组合数,也就是总情况数。

最后把每种 \(k\) 的总情况数乘上 \(k\) 相加即

\[\sum_{k = 0}^{n} (k \times C_{n - k + m - 2} ^ {m - 2}) \]

而这就是答案 \(ans\)。

最后输出 \(ans \times sum \bmod p\) 即可。

注意当 \(m = 1\) 的时候需要特判


#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

typedef long long LL;

const int N = 11000100;

int n, m, p;
int f[N];
int sum;

int qmi(int a, int k, int p)
{
    int res = 1;
    while (k)
    {
        if (k & 1) res = (LL)res * a % p;
        k >>= 1;
        a = (LL)a * a % p;
    }
    return res;
}

int in_f(int x) // 逆元
{
    return qmi(x, p - 2, p);
}

int C(int a, int b)
{
    if (a < b) return 0; // 一定要判断,不然会re,可能本地没问题,但那只是越界不够大而已
    return (LL)f[a] * in_f(f[b]) % p * in_f(f[a - b]) % p; 
}

int lucas(int a, int b) // 获取C(a, b)组合数
{
    if (a < p && b < p) return C(a, b);
    return (LL)C(a % p, b % p) * lucas(a / p, b / p) % p;
}


int main()
{
    cin >> n >> m >> p;
    
    if (m == 1) // 特判
    {
        cout << n % p;
        return 0;
    }
    
    f[0] = 1;
    int maxv = max(m, p - 1);
    for (int i = 1; i <= maxv; i ++ )
    {
        f[i] = (LL)f[i - 1] * i % p;
        if (i <= m) sum = (sum + f[i]) % p; 
    }
    
    int ans = 0;
    for (int i = 0; i <= n; i ++ )
    {
        ans = (ans + (LL)i * lucas(n - i + m - 2, m - 2) % p) % p;
    }
    cout << (LL)ans * sum % p << endl;
    return 0;
}

标签:return,int,sum,times,元力,阶乘,P10380,Round,LL
From: https://www.cnblogs.com/blind5883/p/18212658

相关文章

  • CodeTON Round 3 (Div. 1 + Div. 2, Rated, Prizes!)
    切5道。A\([a_1=1]\)B\(\max(\max(xy),\max(x^2),\max(y^2))\)第一部分可以选整个数组,第二部分和第三部分是最大连续0段和1段。C操作等价于\(a_{l\simr}\oplus1\),\(b_{l\simr}\oplus1\),\(b_{1\simn}\oplus1\)。考虑先把\(a\)全部变成\(0\),使用ii......
  • Codeforces Global Round 12 C2. Errich-Tac-Toe (Hard Version) 题解 构造
    Errich-Tac-Toe(HardVersion)题目描述TheonlydifferencebetweentheeasyandhardversionsisthattokensoftypeOdonotappearintheinputoftheeasyversion.ErrichtogaveMonogonthefollowingchallengeinordertointimidatehimfromtakingh......
  • CF Round946 (Div. 3)C:map的map<pair<int,int>int>映射 + 性质
    BeautifulTriplePairs题目描述Polycarpwasgivenanarray$a$of$n$integers.Hereallylikestriplesofnumbers,soforeach$j$($1\lej\len-2$)hewrotedownatripleofelements$[a_j,a_{j+1},a_{j+2}]$.Polycarpconsidersapa......
  • Codeforces Round 946 (Div. 3) G Money Buys Less Happiness Now(反悔贪心)
    MoneyBuysLessHappinessNow1.题目大意:有n天,每天可以赚x块钱,然后每天可以通过花\(C_{i}\)块钱购买1点快乐值,然后每天赚的钱至少要在下一天才能用,问最多能获得多少快乐值。2.解题思路:我们发现天数变得很多,不能像e题那样dp了,所以要用贪心。具体来讲,我们碰到当前能买的就直接......
  • Codeforces Round 946 (Div. 3)
    C.BeautifulTriplePairs题意:优美组的定义是一共三对有且只有一对对应的数字不相同,求有多少个优美三元组思路:对于只有三对,而且只有一对不同,首先看前面遍历过的三元组会对后面的三元组产生影响,若是不记录前面对后面三元组的次数,那么我们要进行两次循环O(n^2)会寄的,因此我们......
  • loj#575. 「LibreOJ NOI Round #2」不等关系
    记事件\(A\)为「当\(s_i=\texttt<\)时\(p_i<p_{i+1}\)」,事件\(B\)为「当\(s_i=\texttt<\)时\(p_i<p_{i+1}\),且存在\(s_j=\texttt>\),满足\(p_i<p_{i+1}\)。所求即\(n(A)-n(B)\)。\(n(A)\)是好求的,相当于部分定序排列,记每个递增段的长度为\(a_1......
  • CF Round946 (Div. 3)B:如何写映射
    SymmetricEncoding题目描述Polycarphasastring$s$,whichconsistsoflowercaseLatinletters.Heencodesthisstringusingthefollowingalgorithm:first,heconstructsanewauxiliarystring$r$,whichconsistsofalldistinctlettersofthestrin......
  • Codeforces Round 946 (Div. 3)
    CodeforcesRound946(Div.3)总结:赛时状态很好,做出了感觉平常会赛时寄掉但是赛后补题的E,但是也因此花费时间太多,没时间去做更简单的F和G,赛后G用时十分钟AC,F码的有点麻烦,用时40分钟左右,感觉三个小时能AK?A.PhoneDesktop题意:给定3*5的平面,有a个1*1的格子和b个2*2的格子,求完全......
  • “现代汽车中国前瞻软件赛杯” 牛客周赛 Round 43 D、E
     那时候吃了饭后,剩下25分钟,我就把A-D都过了一遍,E不够时间。 D对于x~y这个长度为k的序列:对于1~k每个数,它出现的数目。从x~y,到x+1~y:如果一个数出现的数目从0->1,出现元素数目+1;如果一个数出现的数目从1->0,出现元素数目-1。记录所有出现元素数目=k的序列。太多人对了。......
  • Codeforces Round 945 (Div. 2) (A - E)
    A每一轮对总分的贡献都是\(2\),如果\(p_1+p_2+p_3\)为奇数则无解。\(p_1+p_2\lep_3\),最多\(p_1+p_2\)轮。\(p_1+p_2>p_3\),可以\(1,2\)轮流将\(3\)耗完,然后互相匹配,最多\(\dfrac{p_1+p_2+p_3}{2}\)。B如何判断一个\(k_0\)是否符合条件?处......