YACS 2023年8月月赛 甲组 T1 不定方程 题解

题目链接

背包

首先想到背包,fi,j 为前 i 个数和为 j 的方案数,但时间复杂度为 O(n20000000),会炸。

如果背包跑的时候只跑到当前的 sum,就能得到常数的优化,但仍然不足以通过。

插板法

先来考虑一个更简单的问题,每个 ai 只有下界为 1 该怎么做,不妨想象有 m 个花盆,需要在其中插 n1 个板子将它们分成 n 个部分。

这样就是答案了吧,所以没有上界时的答案为 C(m1,n1)

上界相同的解法

如果对于每个 ai 除了有下界 1,还有一个共同的上界 k,那又该如何解决呢?显然能够想到容斥。

答案就是只有下界的方案数-有一个越界剩下只有下界的方案数+有两个越界剩下只有下界的方案数-有三个越界剩下只有下界的方案数......

其中有 m 个越界的方案数就是 C(n,m)C(sumik,n1)

上界不同的解法

直接进行容斥原理 dfs 即可,但 m 很大,有 1e9,算  C 会超时。

但容易发现即使 ai 都取到 1000000n 个加起来也只有 2e7,所以 m>2e7 时无解,剩下预处理即可。

代码:

复制代码
#include<iostream>
#define int long long
using namespace std;
int n,m;
int a[21],fac[20000001];
const int mod=1000000007;
int q_pow(int x,int y){
    if(y==0)return 1;
    if(y&1)return x*q_pow(x*x%mod,y>>1)%mod;
    return q_pow(x*x%mod,y>>1);
}
int inv(int x){return q_pow(x,mod-2);}
int C(int n,int m){
    if(n<m)return 0;
    if(n==m)return 1;
    return fac[n]*inv(fac[m])%mod*inv(fac[n-m])%mod;
}
int dfs(int x,int r){
    //x:目前是第几个
    //r:目前还有几个 1 没分配
    if(x==n+1)return C(r-1,n-1);
    return (dfs(x+1,r)-dfs(x+1,r-a[x])+mod)%mod;
}
signed main(){
    fac[0]=1;
    for(int i=1;i<=20000000;i++)fac[i]=fac[i-1]*i%mod;
    cin>>n>>m;
    if(m>20000000){
        cout<<0;
        return 0;
    }
    for(int i=1;i<=n;i++)cin>>a[i];
    cout<<dfs(1,m);
    return 0;
}
复制代码

 

posted @   Xy_top  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示