奇怪的分组 组合数

36 篇文章 0 订阅
35 篇文章 0 订阅

背景描述:
终于解出了dm同学的难题,dm同学同意帮v神联络。可dm同学有个习惯,就是联络同学的时候喜欢分组联络,而且分组的方式也很特别,要求第i组的的人数必须大于他指定的个数ci。在dm同学联络的时候,v神在想,按照dm同学的规则一共可以有多少种方案呢?他想啊想,终于……没想出来。于是他又想到了聪明的你,你能帮v神算出按照dm同学的规则有多少种分组方案吗?
题目描述:
v神的班级共有n个人,dm同学想把同学分成M组联络,要求第i组的人数必须大于给定的正整数Ci,求有多少不同的方案?(两个是相同的方案当且仅当对于任意的一队i,两个方案的第i组同学数量相等)由于结果很大,所以你只需要输出模1000000007的值。

输入格式:
第一行两个整数N和M ,后面有M行,每行一个整数,表示Ci

输出格式:
仅有一行,一个整数,方案数模1000000007的值。

样例输入:
10 3
1
2
3


样例输出:
3

样例解释:
方案有三种,每堆的个数分别是(3,3,4),(2,4,4),(2,3,5)。

数据范围约定:
对于30%的数据,N ,M<= 10
对于60%的数据,N ,M<=1000
对于100%的数据,N ,M<= 1000000 Ci<=1000
数据保证至少有一个方案

const md=800000;
md2=1000000007;
type arr=array[0..800000] of longint;
var n,m,i,j,k:longint;
sum:int64;
su,a,b:arr;
v:array[0..2000000] of boolean;
procedure sushu;
var i,j:longint;
begin
 for i:=2 to md do
  if not v[i] then
   begin
    j:=i;
    repeat
     inc(j,i); v[j]:=true;
    until j>md;
   end;
 for i:=2 to md do
  if not v[i] then
   begin
    inc(su[0]); su[su[0]]:=i;
   end;
end;
procedure fenjie(x:longint; var d:arr);
var i,j:longint;
now:int64; //fuck 
begin
 for i:=1 to su[0] do
  if su[i]>x then exit
  else
   begin
    now:=su[i];
    while (now<=md) do
     begin
      inc(d[i],x div now); now:=now*su[i];
     end;
   end;
end;
procedure main;
var i,j:longint;
begin
 dec(n); dec(m);
 fenjie(n,a); fenjie(n-m,b); fenjie(m,b);
 for i:=1 to su[0] do
  a[i]:=a[i]-b[i];
 sum:=1;
 for i:=1 to su[0] do
  for j:=1 to a[i] do
   sum:=(sum*su[i]) mod md2;
end;
begin
 assign(input,'input.in'); assign(output,'output.out');
 reset(input); rewrite(output);
 readln(n,m);
 sushu;
 for i:=1 to m do
  begin
   readln(j); dec(n,j);
  end;
 main;
 writeln(sum);
 close(input); close(output);
end.


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值