Luogu4640 BJWC2008 王之财宝 容斥、Lucas

传送门

题意:有$N$种物品,其中$T$个物品有限定数量$B_i$,其他则没有限定。问从中取出不超过$M$个物品的方案数,对质数$P$取模。$N,M \leq 10^9 , T \leq 15 , P \leq 10^5$


在$N$种物品中选出不超过$M$种物品的方案数可以用插板法(插板法只能满足刚好$M$个,那么我们可以虚构出一个数量无限的物品,把剩下的没选择完的都丢给它,这样插板法就能做了)

发现$T$很小,直接容斥。$N,M \leq 10^9$不能直接预处理,考虑到$P$为质数且范围较小,可以使用$Lucas$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 inline int read(){
 5     int a = 0;
 6     bool f = 0;
 7     char c = getchar();
 8     while(c != EOF && !isdigit(c)){
 9         if(c == '-')
10             f = 1;
11         c = getchar();
12     }
13     while(c != EOF && isdigit(c)){
14         a = (a << 3) + (a << 1) + (c ^ '0');
15         c = getchar();
16     }
17     return f ? -a : a;
18 }
19 
20 const int MAXN = 100000;
21 int N , M , P , Q , jc[MAXN + 10] , ny[MAXN + 10] , B[16] , ans;
22 
23 inline int poww(long long a , int b){
24     int times = 1;
25     while(b){
26         if(b & 1)
27             times = times * a % Q;
28         a = a * a % Q;
29         b >>= 1;
30     }
31     return times;
32 }
33 
34 inline int C(int N , int M){
35     if(N < 0 || M < 0 || N < M)
36         return 0;
37     return 1ll * jc[N] * ny[M] % Q * ny[N - M] % Q;
38 }
39 
40 int lucas(int N , int M){
41     if(N + M == 0)
42         return 1;
43     return 1ll * C(N % Q , M % Q) * lucas(N / Q , M / Q) % Q;
44 }
45 
46 void choose(int now , int num , int cnt){
47     if(num < 0)
48         return;
49     if(now > M)
50         ans = (ans + (cnt & 1 ? -1ll : 1ll) * lucas(num + N , N) + Q) % Q;
51     else{
52         choose(now + 1 , num , cnt);
53         choose(now + 1 , num - B[now] - 1 , cnt + 1);
54     }
55 }        
56 
57 int main(){
58 #ifdef LG
59     freopen("4640.in" , "r" , stdin);
60 #endif
61     N = read();
62     M = read();
63     P = read();
64     Q = read();
65     jc[0] = ny[0] = 1;
66     for(long long i = 1 ; i < Q ; i++)
67         jc[i] = jc[i - 1] * i % Q;
68     ny[Q - 1] = poww(jc[Q - 1] , Q - 2);
69     for(long long i = Q - 2 ; i ; i--)
70         ny[i] = ny[i + 1] * (i + 1) % Q;
71     for(int i = 1 ; i <= M ; i++)
72         B[i] = read();
73     choose(1 , P , 0);
74     cout << ans;
75     return 0;
76 }

转载于:https://www.cnblogs.com/Itst/p/9867615.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在信号处理领域,DOA(Direction of Arrival)估计是一项关键技术,主要用于确定多个信号源到达接收阵列的方向。本文将详细探讨三种ESPRIT(Estimation of Signal Parameters via Rotational Invariance Techniques)算法在DOA估计中的实现,以及它们在MATLAB环境中的具体应用。 ESPRIT算法是由Paul Kailath等人于1986年提出的,其核心思想是利用阵列数据的旋转不变性来估计信号源的角度。这种算法相比传统的 MUSIC(Multiple Signal Classification)算法具有较低的计算复杂度,且无需进行特征值分解,因此在实际应用中颇具优势。 1. 普通ESPRIT算法 普通ESPRIT算法分为两个主要步骤:构造等效旋转不变系统和估计角度。通过空间平移(如延时)构建两个子阵列,使得它们之间的关系具有旋转不变性。然后,通过对子阵列数据进行最小二乘拟合,可以得到信号源的角频率估计,进一步转换为DOA估计。 2. 常规ESPRIT算法实现 在描述中提到的`common_esprit_method1.m`和`common_esprit_method2.m`是两种不同的普通ESPRIT算法实现。它们可能在实现细节上略有差异,比如选择子阵列的方式、参数估计的策略等。MATLAB代码通常会包含预处理步骤(如数据归一化)、子阵列构造、旋转不变性矩阵的建立、最小二乘估计等部分。通过运行这两个文件,可以比较它们在估计精度和计算效率上的异同。 3. TLS_ESPRIT算法 TLS(Total Least Squares)ESPRIT是对普通ESPRIT的优化,它考虑了数据噪声的影响,提高了估计的稳健性。在TLS_ESPRIT算法中,不假设数据噪声是高斯白噪声,而是采用总最小二乘准则来拟合数据。这使得算法在噪声环境下表现更优。`TLS_esprit.m`文件应该包含了TLS_ESPRIT算法的完整实现,包括TLS估计的步骤和旋转不变性矩阵的改进处理。 在实际应用中,选择合适的ESPRIT变体取决于系统条件,例如噪声水平、信号质量以及计算资源。通过MATLAB实现,研究者和工程师可以方便地比较不同算法的效果,并根据需要进行调整和优化。同时,这些代码也为教学和学习DOA估计提供了一个直观的平台,有助于深入理解ESPRIT算法的工作原理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值