[英]Product modulo random numbers
素数p
是固定的。 给出了 n 个数字的序列,每个数字从1
到p - 1
。 众所周知,序列中的数字是随机选择的,可能性相等且彼此独立。 从序列中选择一些数字,使它们的乘积以p
为模,等于给定的数字x
。 如果没有选择数字,则认为乘积等于 1。
输入:
第一行包含三个由空格分隔的整数:序列的长度n
、素数p
和所需的值x
(n=100, 2<=p<=10^9, 0<x<p)
接下来,写入n
整数,以空格或换行符分隔:序列a1
, a2
,。 . ., an
(0 <ai <p)
输出:
从乘积模p
等于x
的序列中打印数字。 数字显示的顺序并不重要。 如果有多个可能的答案,请打印其中任何一个
例子:
INPUT:
100 11 4
9 6 1 1 10 4 9 10 3 1 10 1 6 8 3 3 9 8
10 3 7 7 1 3 3 1 5 2 10 4 1 5 6 7 2 6
2 8 3 3 6 7 6 3 1 5 10 2 2 10 9 6 8 6
2 10 3 2 7 4 3 2 8 6 4 1 7 2 10 8 4 9
7 9 8 7 4 7 3 2 8 2 3 7 1 5 2 10 7 1 8
6 4 10 10 3 6 10 2 1
OUTPUT:
4 6 10 9
我的解决方案:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n,p,x,y,m,k,tmp;
vector<int> v;
cin >> n >> p >> x;
for (int i = 0; i<n; i++){
cin >> tmp;
v.push_back(tmp);
}
sort(v.begin(), v.end());
v.erase(v.begin(), upper_bound(v.begin(), v.end(), 1));
k=-1;
while(1){
k++;
m = 1;
y = x+p*k;;
vector<int> res;
for (int i = 0; i<n; i++){
if (y == 1) break;
if ( y%v[i] == 0){
res.push_back(v[i]);
m*=v[i];
m%=p;
y = y/v[i];
}
}
if (m==x) {
for (int i = 0; i<res.size(); i++){
cout << res[i] << " ";
}
break;
}
}
return 0;
}
在我的解决方案中,我使用了条件( y=x+k*p
,其中y
是答案中数字的乘积, k
是某种自然数)。 并且还迭代了值k
。
此解决方案有时会超出分配的时间。 请告诉我一个更正确的算法。
我会考虑对输入列表的散列多集进行回溯例程。 由于p
是素数,因此我们可以随时考虑当前倍数m
是否在我们的多重集中(multiplicative_inverse(m, p) * x) % p
( https://en.wikipedia.org/wiki/Multiplicative_inverse ) . 如果它存在,我们就完成了。 否则,尝试乘以我们当前在多重集中访问的相同数字,或乘以下一个(保持乘法模p
的结果)。
请参阅下面的评论以获取 Python 示例代码的链接。 你给出的例子有一些简单的解决方案,所以有一些重要的,以及具有挑战性的例子来测试和改进会很有帮助。 还请说明输出中是否需要多个数字。
您可以使用动态编程方法。 它需要 O(p) 个内存单元和 O(p*n) 次循环迭代。 可能有多种优化(排除处理输入重复,或打印最长/最短选择链)。 以下是最简单和基本的 DP 程序,演示了这种方法。
#include <stdio.h>
#include <stdlib.h>
int data[] = {
9, 6, 1, 1, 10, 4, 9, 10, 3, 1, 10, 1, 6, 8, 3, 3, 9, 8,
10, 3, 7, 7, 1, 3, 3, 1, 5, 2, 10, 4, 1, 5, 6, 7, 2, 6,
2, 8, 3, 3, 6, 7, 6, 3, 1, 5, 10, 2, 2, 10, 9, 6, 8, 6,
2, 10, 3, 2, 7, 4, 3, 2, 8, 6, 4, 1, 7, 2, 10, 8, 4, 9,
7, 9, 8, 7, 4, 7, 3, 2, 8, 2, 3, 7, 1, 5, 2, 10, 7, 1, 8,
6, 4, 10, 10, 3, 6, 10, 2, 1
};
struct elm {
int val; // Value
int prev; // from which elemet we come to this
int n; // add loop cound for prevent multiple use same val
};
void printsol(int n, int p, int x, const int *in) {
struct elm *dp = (struct elm *)calloc(p, sizeof(struct elm));
int i, j;
for(i = 0; i < n; i++) // add initial elements into DP array
dp[in[i]].val = in[i];
for(i = 0; i < n; i++) { // add elements, one by one, to DP array
if(dp[in[i]].val <= 1) // skip secondary "1" multipliers
continue;
for(j = 1; j < p; j++)
if(dp[j].val != 0 && dp[j].n < i) {
int y = ((long)j * in[i]) % p;
dp[y].val = in[i]; // current value, for printout
dp[y].prev = j; // reference to prev element
dp[y].n = n; // loop num, for prevent double reuse
if(x == y && dp[x].n > 0) {
// targed reached - print result, by iterate linklist
int mul = 1;
while(x != 0) {
printf(" %d ", dp[x].val);
mul *= dp[x].val; mul %= p;
x = dp[x].prev;
}
printf("; mul=%d\n", mul);
free(dp);
return;
}
} // for+if
} // for i
free(dp);
}
int main(int argc, char **argv) {
printsol(100, 11, 4, data);
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.