我真的不知道c ++,但我需要在php中翻译算法。你能帮我吗,特别是不清楚行std :: transform(...
任务是: 实现计算正整数的数量的函数,该正整数的数量可以被给定数组中的至少一个素数整除。调用者将确保此数组已排序且仅包含唯一素数,因此您的实现可能会利用这些假设而不需要 检查它们是否真的存在。
只要除数列表保持相对较短,有一种非常有效的算法可以计算任何n值的这些数字。
#include <algorithm>
#include <functional>
#include <iostream>
#include <ostream>
#include <vector>
std::vector<signed int> gen_products_of_n_divisors(
const std::vector<signed int>::const_iterator &start,
const std::vector<signed int>::const_iterator &end,
signed int n)
{
if (n == 1)
{
return std::vector<signed int>(start, end);
}
std::vector<signed int> products;
for (std::vector<signed int>::const_iterator i = start;
i != end; ++i)
{
std::vector<signed int> sub_products =
gen_products_of_n_divisors(i + 1, end, n - 1);
products.resize(products.size() + sub_products.size());
std::transform(sub_products.begin(), sub_products.end(),
products.end() - sub_products.size(),
std::bind1st(std::multiplies<signed int>(), *i));
}
return std::vector<signed int>(products);
}
signed int count_divisibles(signed int n,
const std::vector<signed int> &divisors)
{
signed int total_count = 0;
for (signed int i = 1;
i <= static_cast<signed int>(divisors.size()); ++i)
{
std::vector<signed int> products =
gen_products_of_n_divisors(divisors.begin(),
divisors.end(), i);
signed int sign = 2 * (i % 2) - 1;
for (
std::vector<signed int>::iterator j =
products.begin();
j != products.end(); ++j)
{
total_count += sign * n / (*j);
}
}
return total_count;
}
int main()
{
std::vector<signed int> a;
a.push_back(3);
a.push_back(5);
a.push_back(7);
a.push_back(11);
a.push_back(13);
a.push_back(17);
a.push_back(19);
std::cout << count_divisibles(1000000, a) << std::endl;
}
答案 0 :(得分:0)
如果您熟悉Inclusion–exclusion principle,将更容易理解Toolbox的std :: transform参考及其对子产品(除数组子集成员的乘积)的解释。 }。实际上,作为奇数个数的乘积的子产品增加了除数的总数,而那些是偶数个乘积的子产品从中减去。在下面对C ++程序的C的翻译中,这可能更为明显。
在该计划中,请注意1<<nDiv
为2^nDiv
(其中^表示指数取消)。一组k个元素的幂集中有2^k
个子集。每个不同的子集对应于不同的二进制ID#。 (ID#=“身份证号码”)。如果该元素的位在子集的ID#中设置,则set元素是子集的成员。程序将sign
从-1切换为1或从1切换到-1以跟踪偶数或奇数位。
一个真实的程序(对比这样的玩具演示)应该在product
的最里面的循环中计算count_divisibles()
时检查溢出。
// translation to C of C++ program in question
#include <stdlib.h>
#include <stdio.h>
int count_divisibles(int n, int *divisors, int nDiv) {
int total_count = 0;
int i, it, j, sign, product;
for (i=1; i < 1<<nDiv; ++i) {
product = 1;
sign = -1;
for (j=0, it=i; j<nDiv; ++j, it=it/2) {
if (it & 1) {
product *= divisors[j];
sign = -sign;
}
}
total_count += sign * n/product;
}
return total_count;
}
int main(void) {
int a[] = {3,5,7,11,13,17};
int nDiv = sizeof a / sizeof a[0];
int hi, c, k;
for (hi=1000000; hi; hi/=200) {
for (k=0; k<nDiv; ++k) {
c = count_divisibles(hi, a, k);
printf ("count_divisibles(%d, a, %d) = %6d a[%d]=%d\n",
hi, k, c, k, a[k]);
}
c = count_divisibles(hi, a, nDiv);
printf ("count_divisibles(%d, a, %d) = %6d\n", hi, nDiv, c);
}
return 0;
}