首页 > 其他分享 >hdu 5201(隔板法+容斥原理)

hdu 5201(隔板法+容斥原理)

时间:2023-05-29 18:32:39浏览次数:67  
标签:隔板 hdu distribute 容斥 猴子 5201 ans 桃子 GoKu


The Monkey King



Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)




Problem Description


n peaches. And there are m monkeys (including GoKu), they are numbered from 1 to m, GoKu’s number is 1. GoKu wants to distribute these peaches to themselves. Since GoKu is the King, so he must get the most peach. GoKu wants to know how many different ways he can distribute these peaches. For example n=2, m=3, there is only one way to distribute these peach: 2 0 0.

When given n and m, you are expected to calculate how many different ways GoKu can distribute these peaches. Answer may be very large, output the answer modular 1000000007


 



Input


T indicates the number of test cases.

In the next T lines, each line contains n and m which is mentioned above.

[Technical Specification]

All input items are integers.

1≤T≤25

1≤n,m≤100000


 



Output


For each case,the output should occupies exactly one line.

See the sample for more details.


 



Sample Input


2 2 2 3 5


 



Sample Output


Hint

For the second case, there are five ways. They are

2 1 0 0 0 2 0 1 0 0 2 0 0 1 0 2 0 0 0 1 3 0 0 0 0


 


题意:


要把n个桃子分给m个猴子, 其中第一个猴子的桃子要严格最多的, 问方案数。


思路:


可以枚举分多少个桃子给第一个猴子, 假设为x, 那么分给其他猴子的桃子假设为a[i], 那么a[2] + a[3] + ... + a[m-1] = n - x, 如果没有限制的话, 答案就是f(n-x, m-1), f(x, y) 表示把x个桃子分给y个猴子的方案,显然f(x, y) = C(x + y - 1, x), C是组合数,采用的是隔板法。


有限制的话, 可以根据容斥, 算出总的,然后减去1个猴子比第一个猴子的桃子多的方案,然后加上2个猴子比第一个猴子多的方案。。。



k个猴子比第一个猴子多的方案是C(m-1, k) * f(n - (k + 1) * x, m - 1)。

PS:对n件物品分给m个人,允许若干个人为空的问题,可以看成将这n件物品分成m组,允许若干组为空的问题。将n件物品分成m组,需要m-1块隔板,将这n件物品和m-1块隔板排成一排,占n+m-1个位置,从n+m-1个位置中选m-1个隔板放置即可。



#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define prt(k) cout<<#k" = "<<k<<endl;
using namespace std;
typedef long long ll;

const ll mod = 1e9 + 7;
const int N = 201005;

void add(ll &a, ll b) { a=(a+b)%mod; }
void gcd(ll a, ll b, ll &d, ll &x, ll &y)
{
    if (b==0) {
        d = a; x = 1; y = 0;
    } else {
        gcd(b, a%b, d, y, x);
        y -= a/b * x;
    }
}
ll Inv(ll a)
{
    ll d,x,y;
    gcd(a, mod, d, x, y);
    return d==1 ? (x+mod)%mod : -1;
}
ll inv[N];
ll f[N];
ll C(int n, int m)
{
    if (n<0 || n<m || m<0) return 0;
    return f[n] * inv[n-m] % mod * inv[m] % mod;
}
ll F(int x, int y)
{
    return C(x+y-1, y-1);
}
int main()
{
    f[0] = 1;
    for (int i=1;i<N;i++) {
        f[i] = f[i-1] * i % mod;
    }
    for (int i=0;i<N;i++)
        inv[i] = Inv(f[i]);
    int n, m; int re; cin>>re;
    while (re--)
    {
        cin>> n>>m;
        if (m==1 || n==1) { puts("1"); continue; }
        ll ans = 0;
        for (int x=1;x<=n;x++) {
            int t = (n-x + m-2) / (m-1);
            if (x <= t) continue;
            for (int k=0;n-(k+1)*x>=0;k++) {
                ll tmp = C(m-1, k) * F(n-(k+1)*x, m-1) % mod;
                if (k%2==0) ans = (ans + tmp) % mod;
                else ans = (ans - tmp + mod) % mod;
            }
        }
        printf("%I64d\n", ans);
    }
}







标签:隔板,hdu,distribute,容斥,猴子,5201,ans,桃子,GoKu
From: https://blog.51cto.com/u_16143128/6373501

相关文章

  • hdu 5086(dp)
    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5086题目大意:给出长度为n的数组,然后要求累计里面的每个子串的和。解题思路:这道题直接枚举肯定不行,所以要找递推关系。假设:{1,2,3,4}为某一个序列,假设我们已经找到了{1,2,3},接下来把{4}加入进去;由于{1,2,3}已经有{1},{2},{3},{1,......
  • hdu 5188(限制01背包)
    zhxandcontestTimeLimit:2000/1000MS(Java/Others)    MemoryLimit:65536/65536K(Java/Others)ProblemDescriptionAsoneofthemostpowerfulbrushesintheworld,zhxusuallytakespartinallkindsofcontests.Oneday,zhxtakespar......
  • hdu 5171(矩阵快速幂)
    GTY'sbirthdaygiftTimeLimit:2000/1000MS(Java/Others)    MemoryLimit:65536/65536K(Java/Others)ProblemDescriptiona,b∈S),andadda+b Input2≤n≤100000,1≤k≤1000000000).Thesecondlinecontainsnelementsai......
  • hdu 5157(manacher+前缀和+树状数组)
    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5157解题思路:我们可以先用mancher算法对字符串进行处理,把以每个点为中心的回文串半径求出来,然后进行处理。加入对以p为中心的点,从p-r[i]+1~p都是回文串的开头,那么对于每个回文串(开头是j)只要记录结尾从1~j-1的回文串个数,我们可......
  • hdu:第K小的数(构造二分)
    ProblemDescription给定\(n\)个正整数\(a_1,a_2,\dots,a_n\)和\(m\)个正整数\(b_1,b_2,\dots,b_m\)。请在\(n\timesm\)个\(a_i+b_j(1\leqi\leqn,1\leqj\leqm)\)中,找到第\(k\)小的数(不去重)。Input第一行包含一个正整数\(T(1\leqT\leq10)\),表示测试数据的组数。每组......
  • hdu:Ice Cream Tower(构造二分)
    一座高度为k的塔\(b1,b_2,\dots,b_k\)满足\(2b_1\leqb_2,2b_2\leqb_3,2b_3\leqb_4,\dots,2b{k-1}\leqb_k\)你要从中选择一些数来叠很多座高度为\(k\)的塔,问最多能叠多少座塔。Input第一行包含一个正整数T(1≤T≤10),表示测试数据的组数。每组数据第一行包含两个正整数n,k(2......
  • hdu:序列划分(构造二分)
    ProblemDescription给定\(n\)个正整数\(a_1,a_2,\dots,a_n\),将这个序列从左到右划分成\(m\)段,使得每段至少有一个数。你需要让数字之和最大的那一段的数字和尽可能得小。Input第一行包含一个正整数T(1≤T≤10),表示测试数据的组数。每组数据第一行包含两个正整数n,m(1≤m≤......
  • HDU 1176 免费馅饼(简单动态规划)
    传送门这道题是中文描述的,我相信大家都肯定能够看得懂(滑稽),思路上呢大概就是一个升级版的数塔(点我去看数塔)既然是动态规划问题所以首先肯定要先找出来状态转移方程,我找到的状态转移方程就是a[i][j]+=max(max(a[i+1][j+1],a[i+1][j]),a[i+1][j-1]),其中a[i][j]就是表示第i时刻在k位......
  • HDU 1029 Ignatius and the Princess IV(基础dp)
    传送门题目大意就是给你n个数(保证n为一个奇数),存在一个数出现的次数大于(n+1)/2次,求这个数;这个数出现的次数比其他数出现的次数加起来还多,那么当这个数出现时+1,其他的数出现时-1,最后得到的数为正数。假定一个数为特殊数,若当前数与特殊数相同则cnt++,若不相同则cnt--,如果这时cnt<0,用当......
  • HDU 2084 数塔(动态规划入门)
    传送门中文题就不给大家翻译了(手动滑稽),反正大家都看得懂。这是一道动态规划入门的题目,只需要找出状态转移方程即可。状态方程:dp[i][j]=a[i][j]+max(dp[i+1][j],dp[i+1][j])(dp[i][j]表示从第i层第j个数开始搜能得到的最大数)代码如下:#include<cstring>#include<iostream>#include<......