P & Q(dp)

博客内容讲述了作者在解决一道题目时,由于误读题意导致错误算法意外通过,随后纠正思路并提供了正确的动态规划解决方案。核心在于使用f[i][j]表示在第i个数时,q有j个未匹配的p。通过二分查找确定满足条件的匹配数。在转移过程中确保p和q的匹配数量不超过总答案数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这道题,我乱写。。题都读错了,没看到q,p只能在两个不同的取。错误算法还对(100)了。

正解:
f[i][j]:表示第i个数,q有j个没有匹配,的p没有匹配数.

二分总答案数。只要最后满足f[1+n][mid] >= mid 就好,处理完n个数,q有mid个没有匹配,p有大于等于mid个没有匹配.一定可以匹配出mid个。

对于第i个数,如果它可以分成的p的数量和q 的数量之和大于总答案数,肯定i不能分成这么多个,分成这么多个的话会自己和自己配对,转移时保证p的数量和q 的数量之和小于等于总答案数。

标程:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 55, maxm = 2222;
int f[maxn][maxm], b[maxn], c[maxn][maxn], a[maxn], p1, p2;
int main()
{
	int i, j, ll = 0, rr = 0, mid, ft, k, n;
	scanf("%d", & n);
	for (i = 0; i < n; ++i) scanf("%d", & a[i]);
	scanf("%d%d", & p1, & p2);
	for (i=0;i<n;i++) 
	{
		b[i] = a[i]/p1;
		for (j=0;j<=b[i];j++) c[i][j] = (a[i]-j*p1)/p2;
	}
	for (i=0;i<n;i++) rr += a[i];
	rr /= (p1+p2);
	while (ll < rr) 
	{
		mid = (ll+rr+1) >> 1;
		memset(f,255,sizeof(f));
		f[0][0] = 0;
		for (i=0;i<n;i++)
			for (j=0;j<=40*i;j++) if (f[i][j] >= 0)
				for (k=0;k<=b[i] && k<=mid;k++) 
				{
					ft = c[i][k];
					if (ft > mid-k) ft = mid-k; 
					ft += f[i][j];
					if (ft > f[i+1][j+k]) f[i+1][j+k] = ft;
				}
		if (f[n][mid] >= mid) ll = mid;
		else rr = mid-1;
	}
	cout << ll*(p1+p2) << endl;
}

我自己的乱做狗分代码。

#include<bits/stdc++.h>
using namespace std;
int n, a[55], dp[55][100004], p, q, sum[55];
void read(int &x)
{
	x = 0;  	int ff = 0;   char c = getchar();
	while(c < '0' || c > '9')
	{
		if(c == '-') ff = 1;  c = getchar();
	}
	while(c >= '0' && c <= '9')
	{
		x = x * 10 + c - '0';  c = getchar();
	}
	if(ff) x = -x;
}
int main()
{
	freopen("pq.in","r",stdin);
	freopen("pq.out","w",stdout);
	read(n);
	for(int i = 1; i <= n; i++)
	{
		read(a[i]);
	 sum[i] = a[i] + sum[i-1];
	}
	read(p); read(q);
	if(p > q) swap(p,q);
	for(int i = 1; i <= n; i++)
	{
		int k = a[i] / q;
		for(int j = 0; j <= k; j++)
		 {
		 	int he =  a[i] - j * q;
		 	int ha = he / p;
		 	int hi = max(0, j - ha);
		 	if(hi == 0) dp[i][abs(j-ha)] = j; 
		 	int hehe = sum[i-1] / p;
		 if(ha <= j)	
		 for(int  z = hi; z <= hehe; z++)
		      {
		      dp[i][z - hi] = max(dp[i][z - hi],dp[i-1][z]  + j);
	          }
	     if(ha > j)for(int  z = 0; z <= hehe; z++) dp[i][z+ha - j] = max(dp[i][z+ha - j],dp[i-1][z] + j);}
	}
	int ans = 0;
	for(int i = 0; i <= sum[i] / p; i++)
	{
		ans = max(dp[n][i],ans);
	}
	cout << ans * (p + q);
	return 0;
}

附上题解=、=

看不懂他们发的题解的我。

&lt;think&gt;嗯,用户想知道如何使用给定的大素数p和q,以及对应的dp和dq来进行RSA解密运算c的解密过程。首先,我得回忆一下RSA的基本原理,尤其是涉及中国剩余定理(CRT)的部分。因为用户提到了dp和dq,这通常和CRT优化有关。 根据引用[3],RSA的CRT算法解密步骤可能涉及到p和q分解后的计算。常规RSA解密是用私钥d,但CRT方法可以加速这个过程。用户给出的参数是p、q、dp、dq和密文c。需要明确这些参数的含义。 首先,dp通常是d mod (p-1),而dq是d mod (q-1)。在CRT优化中,解密过程会分别计算m_p = c^dp mod p 和 m_q = c^dq mod q。然后,用CRT组合这两个结果得到最终的明文m。 接下来要考虑的是如何正确执行这些步骤。可能需要检查是否有错误,比如c是否在mod p和mod q下有效。另外,计算m_p和m_q的时候,是否需要先对c进行处理,比如模运算前是否要确保c小于p和q?不过通常RSA的密文c是小于n=p*q的,所以直接取模应该没问题。 然后,组合这两个结果的时候,需要使用CRT的公式。例如,计算差值(m_p - m_q),然后乘以q的逆模p,得到一个系数,再代入总公式m = m_q + q * (系数)。或者另一种方式是使用扩展欧几里得算法来找组合的系数。需要确认这个步骤的正确性。 可能还需要注意,如果m_p和m_q的结果不一致,可能会导致错误,这时候可能需要检查参数是否正确。另外,计算逆元的时候,是否存在逆元的问题,比如q和p是否互质?不过p和q是素数,所以它们互质,逆元肯定存在。 用户提供的引用[3]中提到CRT算法解密的步骤,可能包括计算n=p*q,以及使用dp和dq进行模幂运算。所以步骤应该是: 1. 计算m_p = c^dp mod p 2. 计算m_q = c^dq mod q 3. 计算h = (m_p - m_q) * (q^{-1} mod p) mod p 4. 最终明文m = m_q + h * q 这样是否正确呢?需要验证这个公式的来源。例如,根据CRT,解同余式m &equiv; m_p mod p 和 m &equiv; m_q mod q,解就是m = m_q + q * ((m_p - m_q) * q^{-1} mod p)。是的,这个公式是正确的。 另外,用户可能还需要知道如何计算q的逆元mod p,可以使用扩展欧几里得算法或者Python中的pow函数,如pow(q, -1, p)。 最后,可能需要给出具体的Python代码示例,展示如何用给定的参数进行解密。需要处理大整数的运算,确保在Python中使用pow函数的三参数形式来高效计算模幂。 总结步骤应该是:计算m_p和m_q,计算h,然后组合得到m。需要检查过程中每个步骤的正确性,并注意模运算的正确应用。同时,确保引用了正确的参考文献,比如引用[3]提到的CRT步骤。&lt;/think&gt;### 解答 使用大素数 $p$ 和 $q$ 及其对应的 $d_p$、$d_q$ 进行 RSA 解密时,需通过中国剩余定理(CRT)优化解密过程。具体步骤如下: #### 1. **参数定义与验证** - **$d_p$**:私钥指数 $d$ 对 $(p-1)$ 取模的结果,即 $d_p \equiv d \mod (p-1)$[^3] - **$d_q$**:私钥指数 $d$ 对 $(q-1)$ 取模的结果,即 $d_q \equiv d \mod (q-1)$ - 确保 $c &lt; n$(其中 $n = p \times q$),否则解密无效。 #### 2. **分步计算明文分量** - 计算 $m_p = c^{d_p} \mod p$ 对密文 $c$ 在模 $p$ 下进行幂运算。 - 计算 $m_q = c^{d_q} \mod q$ 对密文 $c$ 在模 $q$ 下进行幂运算。 #### 3. **应用中国剩余定理(CRT)** 通过组合 $m_p$ 和 $m_q$ 得到最终明文 $m$: 1. 计算差值:$h = (m_p - m_q) \mod p$ 2. 计算 $q$ 对 $p$ 的模逆元:$q_{inv} = q^{-1} \mod p$ 3. 修正差值:$h = (h \times q_{inv}) \mod p$ 4. 最终明文:$m = m_q + h \times q$ #### 4. **Python 实现示例** ```python def rsa_crt_decrypt(p, q, dp, dq, c): # 计算 m_p 和 m_q m_p = pow(c, dp, p) m_q = pow(c, dq, q) # 计算 q 的模逆元(对 p 取模) q_inv = pow(q, -1, p) # 应用 CRT 组合结果 h = (m_p - m_q) * q_inv % p m = m_q + h * q return m ``` #### **公式推导(CRT 组合)** $$ \begin{align*} m &amp;\equiv m_p \mod p \\ m &amp;\equiv m_q \mod q \\ \Rightarrow m &amp;= m_q + k \times q \quad (k \in \mathbb{Z}) \\ 代入第一个同余式:m_q + kq &amp;\equiv m_p \mod p \\ \Rightarrow k &amp;\equiv (m_p - m_q) \times q^{-1} \mod p \\ \end{align*} $$ 最终 $m = m_q + q \times [(m_p - m_q) \times q^{-1} \mod p]$。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值