组合数取模

D - Combinations
Given n different objects, you want to take k of them. How many ways to can do it?

For example, say there are 4 items; you want to take 2 of them. So, you can do it 6 ways.

Take 1, 2

Take 1, 3

Take 1, 4

Take 2, 3

Take 2, 4

Take 3, 4

Input
Input starts with an integer T (≤ 2000), denoting the number of test cases.

Each test case contains two integers n (1 ≤ n ≤ 106), k (0 ≤ k ≤ n).

Output
For each case, output the case number and the desired value. Since the result can be very large, you have to print the result modulo 1000003.

Sample Input
3

4 2

5 0

6 4

Sample Output
Case 1: 6

Case 2: 1

Case 3: 15
                                                                              这题目有两种方法



第一种是通俗易懂但要复杂一点的方法,就是你要分解质因数,用桶排记录它们的个数,组合的公式 C(n,m)= n!/(m!*(n-m)!)将n! 的所有质因数累加,m!和(n-m)!的质因数减去,

最后算出这些质因数相乘的值。这就要用到线性筛啊,快速幂等等

附上代码(很长)

  1 var
  2   n,m,i,j,k,t,sum,p:longint;
  3   ans:int64;
  4   mark:array[1..200000] of boolean;
  5   prim,num,markx:array[1..200000] of int64;
  6 function prime(x:longint):longint;
  7   var i,j,k:longint;
  8   begin
  9     k:=0;
 10     for i:=2 to x do
 11       begin
 12         if mark[i]
 13           then
 14             begin
 15               k:=k+1;
 16               prim[k]:=i;
 17               markx[i]:=k;
 18             end;
 19         for j:=1 to k do
 20           begin
 21             if i*prim[j]>m
 22               then break;
 23             mark[i*prim[j]]:=false;
 24             if i mod prim[j]=0
 25               then break;
 26           end;
 27       end;
 28     prime:=k;
 29   end;
 30 function f(a,b:longint):int64;
 31   var y:int64;
 32   begin
 33     t:=1;
 34     y:=a;
 35     while b<>0 do
 36       begin
 37         if (b and 1)=1
 38           then t:=t*y mod p;
 39         y:=y*y mod p;
 40         b:=b shr 1;
 41       end;
 42     f:=t;
 43   end;
 44  
 45 begin
 46   readln(m,n,p);
 47   for i:=1 to m do
 48     mark[i]:=true;
 49   sum:=prime(m);
 50   for i:=2 to m do
 51     begin
 52       if mark[i]
 53         then
 54           begin
 55             inc(num[markx[i]]);
 56             continue;
 57           end;
 58       k:=i;
 59       j:=1;
 60       while (prim[j]<=trunc(sqrt(i)))and(k>1) do
 61         begin
 62           if k mod prim[j]=0
 63             then
 64               while k mod prim[j]=0 do
 65                 begin
 66                   k:=k div prim[j];
 67                   num[j]:=num[j]+1;
 68                 end;
 69           j:=j+1;
 70         end;
 71       if k>1
 72         then inc(num[markx[k]]);
 73     end;
 74   for i:=2 to n do
 75     begin
 76       if mark[i]
 77         then
 78           begin
 79             dec(num[markx[i]]);
 80             continue;
 81           end;
 82       k:=i;
 83       j:=1;
 84       while (prim[j]<=trunc(sqrt(i)))and(k>1) do
 85         begin
 86           if k mod prim[j]=0
 87             then
 88               while k mod prim[j]=0 do
 89                 begin
 90                   k:=k div prim[j];
 91                   num[j]:=num[j]-1;
 92                 end;
 93           j:=j+1;
 94         end;
 95       if k>1
 96         then dec(num[markx[k]]);
 97     end;
 98       for i:=2 to m-n do
 99     begin
100       if mark[i]
101         then
102           begin
103             dec(num[markx[i]]);
104             continue;
105           end;
106       k:=i;
107       j:=1;
108       while (prim[j]<=trunc(sqrt(i)))and(k>1) do
109         begin
110           if k mod prim[j]=0
111             then
112               while k mod prim[j]=0 do
113                 begin
114                   k:=k div prim[j];
115                   num[j]:=num[j]-1;
116                 end;
117           j:=j+1;
118         end;
119       if k>1
120         then dec(num[markx[k]]);
121     end;
122  
123   ans:=1;
124   for i:=1 to sum do
125      if num[i]>0
126        then ans:=(ans*f(prim[i],num[i])) mod p;
127   writeln(ans);
128 end.
View Code

第二种就要简单多了,直接算,但是因为要取模,模数又很大,不能直接取模,要用到逆元,就是乘上逆元再模。求逆元呢,要用到扩展欧几里得。再就是一点组合数的运算了

 1 var
 2 l,t,i,modd:longint;
 3 f,inv:array[0..1100005]of int64;
 4 n,m:int64;
 5 function exgcd(a,b:int64;var x,y:int64):int64;
 6  var r,t:int64;
 7  begin
 8    if b=0 then
 9     begin
10       x:=1;
11       y:=0;
12       exit(a);
13     end;
14     r:=exgcd(b,a mod b,x,y);
15     t:=x;
16     x:=y;
17     y:=t-a div b*y;
18     exit(r);
19  end;
20 function cal(d,m:int64):int64;
21  var x,y:int64;
22   begin
23    exgcd(d,m,x,y);
24    exit((x mod m+m) mod m);
25  end;
26  function c(a,b:int64):int64;
27   begin
28    exit(f[a]*inv[b]mod modd *inv[a-b] mod modd);
29   end;
30 begin
31 readln(t);
32 modd:=1000003;
33 f[0]:=1;inv[0]:=1;
34 for i:=1 to 1010000 do
35  begin
36   f[i]:=f[i-1]*i mod modd;
37   inv[i]:=cal(f[i],modd);
38  end;
39 
40 for l:=1 to t do
41  begin
42   readln(n,m);
43 //  if m=0 then begin writeln(1); continue; end; 不要想当然乱加条件,先试试程序对于特殊样例能不能过,能过就不要加初始条件了
44   writeln('Case ',l,': ',c(n,m));
45  end;
46 end.

 

转载于:https://www.cnblogs.com/brilliant107/p/9448275.html

内容概要:本文档详细介绍了Analog Devices公司生产的AD8436真均方根-直流(RMS-to-DC)转换器的技术细节及其应用场景。AD8436由三个独立块构成:轨到轨FET输入放大器、高动态范围均方根计算内核和精密轨到轨输出放大器。该器件不仅体积小巧、功耗低,而且具有广泛的输入电压范围和快速响应特性。文档涵盖了AD8436的工作原理、配置选项、外部组件选择(如电容)、增益调节、单电源供电、电流互感器配置、接地故障检测、三相电源监测等方面的内容。此外,还特别强调了PCB设计注意事项和误差源分析,旨在帮助工程师更好地理解和应用这款高性能的RMS-DC转换器。 适合人群:从事拟电路设计的专业工程师和技术人员,尤其是那些需要精确测量交流电信号均方根值的应用开发者。 使用场景及目标:①用于工业自动化、医疗设备、电力监控等领域,实现对交流电压或电流的精准测量;②适用于手持式数字万用表及其他便携式仪器仪表,提供高效的单电源解决方案;③在电流互感器配置中,用于检测微小的电流变化,保障电气安全;④应用于三相电力系统监控,优化建立时间和转换精度。 其他说明:为了确保最佳性能,文档推荐使用高质量的电容器件,并给出了详细的PCB布局指导。同时提醒用户关注电介质吸收和泄漏电流等因素对测量准确性的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值