组合数学这块因为刷的比较慢,有些题目step都是做过的,加上几道水题,不再发了,简单拿两道排列组合的代表性题目总结总结。
吃糖果:典型的排列组合
高中数学题一个典型题就是插空的排列组合,想让相同的不相邻,插空是首选。
把最多的汤拔出来,形成max-1个空位,剩下的谈只要比这些空位多即可满足不相邻了
即max-1<=sum-max
Combinations
计算C(n,m)
阶乘超范围,做点小处理,用gcd约小。或者直接java水过
吃糖果
HOHO,终于从Speakless手上赢走了所有的糖果,是Gardon吃糖果时有个特殊的癖好,就是不喜欢将一样的糖果放在一起吃,喜欢先吃一种,下一次吃另一种,这样;可是Gardon不知道是否存在一种吃糖果的顺序使得他能把所有糖果都吃完?请你写个程序帮忙计算一下。
Input第一行有一个整数T,接下来T组数据,每组数据占2行,第一行是一个整数N(0<N<=1000000),第二行是N个数,表示N种糖果的数目Mi(0<Mi<=1000000)。
Output对于每组数据,输出一行,包含一个"Yes"或者"No"。
Sample Input
2 3 4 1 1 5 5 4 3 2 1Sample Output
No
Yes
Please use function scanf
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
#define MOD 1000000007
#define N 1000010
//int map[N];
int main()
{
int n;
int temp;
int t;
cin>>t;
while(t--)
{
scanf("%d",&n);
int maxv=-1;
ll sum=0;
//memset(map,0,sizeof(map));
for(int i=1;i<=n;i++)
{
scanf("%d",&temp);
sum+=temp;
maxv=max(temp,maxv);
}
if(maxv<=1+sum-maxv)
cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
Combinations
Computing the exact number of ways that N things can be taken M at a time can be a great challenge when N and/or M become very large. Challenges are the stuff of contests. Therefore, you are to make just such a computation given the following:
GIVEN: 5 <= N <= 100; 5 <= M <= 100; M <= N
Compute the EXACT value of: C = N! / (N-M)!M!
You may assume that the final value of C will fit in a 32-bit Pascal LongInt or a C long. For the record, the exact value of 100! is:
93,326,215,443,944,152,681,699,238,856,266,700,490,715,968,264,381,621, 468,592,963,895,217,599,993,229,915,608,941,463,976,156,518,286,253, 697,920,827,223,758,251,185,210,916,864,000,000,000,000,000,000,000,000
Input
GIVEN: 5 <= N <= 100; 5 <= M <= 100; M <= N
Compute the EXACT value of: C = N! / (N-M)!M!
You may assume that the final value of C will fit in a 32-bit Pascal LongInt or a C long. For the record, the exact value of 100! is:
93,326,215,443,944,152,681,699,238,856,266,700,490,715,968,264,381,621, 468,592,963,895,217,599,993,229,915,608,941,463,976,156,518,286,253, 697,920,827,223,758,251,185,210,916,864,000,000,000,000,000,000,000,000
The input to this program will be one or more lines each containing zero or more leading spaces, a value for N, one or more spaces, and a value for M. The last line of the input file will contain a dummy N, M pair with both values equal to zero. Your program should terminate when this line is read.
Output
The output from this program should be in the form:
N things taken M at a time is C exactly.
Sample Input
N things taken M at a time is C exactly.
100 6 20 5 18 6 0 0Sample Output
100 things taken 6 at a time is 1192052400 exactly. 20 things taken 5 at a time is 15504 exactly. 18 things taken 6 at a time is 18564 exactly.
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
#define MOD 1000000007
#define N 1000010
ll gcd(ll a,ll b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
int main()
{
int n,m;
while(cin>>n>>m)
{
if(n==0&&m==0)
break;
ll ans=1;
int j=2;
ll temp=1;
int a=max(m,n-m);
int b=min(m,n-m);
for(int i=n;i>a;i--)
{
ans*=i;
if(j<=b||temp>1)
{
if (j<=b)
temp*=j;
if (temp>1)
{
ll GCD=gcd(ans,temp);
ans/=GCD;
temp/=GCD;
}
}
j++;
}
cout<<n<<" things taken "<<m<<" at a time is ";
cout<<ans<<" exactly."<<endl;
}
return 0;
}