Noip2016day2 组合数问题problem

题目描述

组合数表示的是从n个物品中选出m个物品的方案数。举个例子,从(1,2,3) 三个物品中选择两个物品可以有(1,2),(1,3),(2,3)这三种选择方法。根据组合数的定 义,我们可以给出计算组合数的一般公式:

其中n! = 1 × 2 × · · · × n

小葱想知道如果给定n,m和k,对于所有的0 <= i <= n,0 <= j <= min(i,m)有多少对 (i,j)满足是k的倍数。

输入输出格式

输入格式:

第一行有两个整数t,k,其中t代表该测试点总共有多少组测试数据,k的意义见 【问题描述】。

接下来t行每行两个整数n,m,其中n,m的意义见【问题描述】。

输出格式:

t行,每行一个整数代表答案。

输入输出样例

输入样例#1

1 2

3 3

输出样例#1

1

输入样例#2

2 5

4 5

6 7

输出样例#2

0

7

说明

【样例1说明】

在所有可能的情况中,只有是2的倍数。

【子任务】

思路

这是一道数论题

首先要知道组合数的一般递推公式,它的递推公式和杨辉三角是一样的

c[i][j]=c[i-1][j-1]+c[i-1][j]

(解释:c[i][j]即为从i件物品中选j件的方案数。如果第i件物品不选,方案数就变为c[i-1][j],如果选第i件物品,方案数就变为c[i-1][j-1],总方案数就为两种情况的方案数之和)

为了不爆long long,每次求出c[i][j]后先模一下k

为了节约时间,进行二维求和,最后直接查找答案

#include<iostream>
using namespace std;
int n,m,t,k;
int c[2001][2001],s[2001][2001];
void get_c()
{
    for(int i=0;i<=2000;i++)
    {
        for(int j=0;j<=i;j++)
        {
            if(i==0&&j==0)c[i][j]=1%k;
            else
            {
                c[i][j]=(c[i-1][j]+c[i-1][j-1])%k;
            }
        }
    }
}
void get_s()
{
    if(c[0][0]==0)s[0][0]=1;
    for(int i=0;i<=2000;i++)
    {
        for(int j=0;j<=i;j++)
        {
            if(i==0&&j==0)continue;
            else
            {
                if((i==0&&j)||(i==j)){
                    s[i][j]=s[i][j-1];
                    if(c[i][j]==0)s[i][j]++;
                }
                else if(i&&j==0){
                    s[i][j]=s[i-1][j];
                    if(c[i][j]==0)s[i][j]++;
                }
                else if(i&&j)
                {
                    s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
                    if(c[i][j]==0)s[i][j]++;
                }
            }
        }
    }
}
int main()
{
    cin>>t>>k;
    get_c();
    get_s();
    while(t--)
    {
        cin>>n>>m;
        cout<<s[n][min(n,m)]<<endl;
    }
}
时间: 2024-10-10 23:23:59

Noip2016day2 组合数问题problem的相关文章

FZU 1753-Another Easy Problem(求多个组合数的最大公约数)

Another Easy Problem Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice FZU 1753 Appoint description:  xietutu  (2013-03-13)System Crawler  (2015-04-27) Description 小TT最近学习了高斯消元法解方程组,现在他的问题来了,如果是以下的方程,

Light OJ 1102 Problem Makes Problem 组合数

#include <iostream> #include <string> #include <map> #include <vector> #include<algorithm> using namespace std; typedef pair<string,int>PAIR; bool cmp_by_value(const PAIR& p,const PAIR &a) { return p.second<a

(light oj 1102) Problem Makes Problem (组合数 + 乘法逆元)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1102 As I am fond of making easier problems, I discovered a problem. Actually, the problem is 'how can you make n by adding k non-negative integers?' I think a small example will make things clea

hdu 1792 A New Change Problem(互质数之间最大不能组合数和不能组合数的个数)

题意:求互质的m和n的最大不能组合数和不能组合数的个数 思路:m和n的最大不能组合数为m*n-m-n,不能组合数的个数为(m-1)*(n-1)/2 推导: 先讨论最大不能组合数 因为gcd(m,n)=1,所以 0,n,2*n,3*n,...(m-1)*n(共m个数字)分别除以m,余数肯定不同,且为{0,1,2,3...m-1}中的某数 若存在非负数p,q使得pm+qn=x,x为可组合值,两边对m取余,则(q*n)%m==x%m,p*m>=0,所以只要x>q*n,x都能被组合出来.当q<m

Codeforces1153F Serval and Bonus Problem 【组合数】

题目分析: 我们思考正好被k个区间覆盖的情况,那么当前这个子段是不是把所有的点分成了两个部分,那么在两个部分之间相互连k条线,再对于剩下的分别连线就很好了?这个东西不难用组合数写出来. 然后我们要证明每个区间的期望长度是点数加一分之一,这个很容易,归纳法证明就行了. 代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int mod = 998244353; 5 6 int n,k,l; 7 int f[10200];

杭电1023Train Problem II

地址:http://acm.hdu.edu.cn/showproblem.php?pid=1023 题目: Train Problem II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7675    Accepted Submission(s): 4131 Problem Description As we all know the

[Swust OJ 247]--皇帝的新衣(组合数+Lucas定理)

题目链接:http://acm.swust.edu.cn/problem/0247/ Time limit(ms): 1000 Memory limit(kb): 65535 Description 在很久很久以前,有个臭美国王.一天,他得到了一件新衣,于是决定巡城看看老百姓的反应(囧).于是他命令可怜的宰相数一下他有多少种巡城方案. 城市是一个N*M的矩形,(N+1)*(M+1)条街把城市分成了N*M块.国王从左下角出发,每次只能向右或向上走,右上角是终点. 请你帮帮可怜的宰相. Input

hunnu--11547--你的组合数学学得如何?

你的组合数学学得如何?  Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB Total submit users: 151, Accepted users: 119 Problem 11547 : No special judgement Problem description   小明和小红总是喜欢在一起玩.一天,他们又在一起愉快的玩耍了一个下午,到了吃晚饭的时间,他们决定用抛硬币的方法来决定谁请吃晚餐. 规

UVa 729 - The Hamming Distance Problem

题目:构造n位01串,其中有m个1的所有组合. 分析:搜索.枚举.可以利用库函数,求解,也可以利用dfs求解:我这里采用位运算计算组合数. 说明:注意库啊! #include <iostream> #include <cstdlib> #include <cstdio> using namespace std; int S[20]; int main() { int T,N,M; while ( cin >> T ) for ( int t = 1 ; t