当前位置: 首页 > 知识库问答 >
问题:

一个数的最大除数与质因数的关系

燕元明
2023-03-14

问题如下:给定两个数字n和k。对于区间[1, n]中的每个数字,您的任务是计算其不可被k整除的最大除数。打印所有这些除数的和。注意:k始终是质数。t=3*10^5,1

我解决这个问题的方法是:对于1到n范围内的每个i,所需的除数是i本身,只有当i不是k的倍数时。如果i是k的倍数,那么我们必须找到一个数字的最大除数并与k匹配。如果不匹配,那么这个除数就是我的答案。否则,第二大除数就是我的答案。

例如,取n=10和k=2,1到10范围内每个i的必需因子是1,1,3,1,5,3,7,1,9,5。这些因子的总和是36。所以ans=36。

我的代码,对一些测试用例有效,但对一些测试用例无效。

#include<bits/stdc++.h>
using namespace std;
#define ll long long int

ll div2(ll n, ll k) {
if (n % k != 0 || n == 1) {
    return n;
}

else {
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) {
            ll aa = n / i;
            if (aa % k != 0) {
                return aa;
            }
        }
    }
}
return 1;
}



int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;

while (t--) {
    ll n, k;
    cin >> n >> k;
    ll sum = 0, pp;

    for (pp = 1; pp <= n; pp++) {
        //cout << div2(pp, k);
        sum = sum + div2(pp, k);
    }
    cout << sum << '\n';
 }

 }

有人能帮助我哪里做错了,或者建议我一些更快的逻辑来做这个问题,因为我的一些测试案例显示超过了时间限制

在查看了所有可能的解释之后,我修改了我的代码,如下所示:

#include<bits/stdc++.h>
using namespace std;
#define ll long long int

int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;

while (t--) {
    ll n, i;
    ll k, sum;
    cin >> n >> k;

    sum = (n * (n + 1)) / 2;

    for (i = k; i <= n; i = i + k) {
        ll dmax = i / k;

        while (dmax % k == 0) {
            dmax = dmax / k;
        }
        sum = (sum - i) + dmax;

    }
    cout << sum << '\n';

}

}

但它仍然给出了3个测试用例的时间限制超过。有人请帮忙。

共有3个答案

袁何平
2023-03-14

我想知道这样的事情是否是一个莱纳的意思。

(注意,这段代码有两个错误,在评论中有描述,也可以用One Lyner的新代码来说明。)

C代码:

#include <vector>
#include <iostream>
using namespace std;
#define ll long long int

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int t;
    cin >> t;

    while (t--) {
        ll n;
        ll k, _k, result;
        vector<ll> powers;
        cin >> n >> k;

        result = n * (n + 1) / 2;
        _k = k;

        while (_k <= n) {
            powers.push_back(_k);
            _k = _k * k;
        }

        for (ll p : powers) {
            ll num_js = n / p;
            result -= num_js * (num_js + 1) / 2 * (p - 1);
            int i = 0;
            while (p * powers[i] <= n) {
                result += powers[i] * (p - 1);
                i = i + 1;
            }
        }

        cout << result << '\n';
    }
}
岳正阳
2023-03-14

这本身更像是一个数学问题:如果cur = [1..n],正如你已经注意到的,最大除数= dmax = cur是,如果cur % k!= 0,否则dmax必须为

因此,这应该是这样的(没有保证只是输入了-也许我在思考中遗漏了一些东西):

#include <iostream>

int main() {
    unsigned long long n = 10;
    unsigned long long k = 2;

    for (auto cur_n = decltype(n){1}; cur_n <= n; cur_n++)
    {
        if (cur_n % k != 0) {
            std::cout << "Largest divisor for " << cur_n << ": " << cur_n << " (SELF)" << std::endl;
        } else {
            unsigned long long dmax= cur_n/k;

            while (dmax%k == 0)
                dmax= dmax/k;
            std::cout << "Largest divisor for " << cur_n << ": " << dmax<< std::endl;
        }
    }
}
危飞文
2023-03-14

就像其他人已经说过的,看看约束:t=3*10^5,1

如果您的测试具有通过循环计算总和的复杂度O(n),您最终将执行t*n~10^14。那太多了。

这是一个数学挑战。您需要使用两个事实:

    < li >正如您已经看到的,如果< code>i = j * k^s与< code>j%k!= 0,最大除数为< code > j ;
  • sum_{i=1}^t I =(t *(t ^ 1))/2

我们从

S = sum(range(1, n)) = n * (n+1) / 2

然后对于所有形式 k * x 的数字,我们加了太多,让我们纠正:

S = S - sum(k*x for x in range(1, n/k)) + sum(x for x in range(1, n/k))
  = S - (k - 1) * (n/k) * (n/k + 1) / 2

继续输入k^2*x形式的数字…然后k^p*x直到总和为空…

好的,人们开始编写代码,所以这是一个小的Python函数

def so61867604(n, k):
    S = (n * (n+1)) // 2
    k_pow = k
    while k_pow <= n:
        up = n // k_pow
        S = S - (k - 1) * (up * (up + 1)) // 2
        k_pow *= k
    return S

在这里行动https://repl.it/repls/OlivedrabKeyProjections

 类似资料:
  • 使用椭圆曲线分解(在Python中),我能够在~0.5秒内找到50位数字的PRIME因子。有什么方法可以将质因数转换为数字的因子吗? 通过对小数位(496和28)进行测试,将质因数按特定顺序相乘,我实现了什么。然后,将这些数字相乘,几乎就能得到因数,但这并不太灵活,因为我只从一个小的质因数列表(1,2,3,5)中得到需要相乘的公式。

  • 本文向大家介绍Java数组中最大质数和最小质数之间的差异,包括了Java数组中最大质数和最小质数之间的差异的使用技巧和注意事项,需要的朋友参考一下 问题陈述 对于给定的整数数组,其中所有元素均小于1000000。找到数组中最大素数和最小素数之间的差。 示例 解 使用Eratosthenes筛分法,这是找出小于给定数的所有素数的有效方法。然后,我们将找出最大和最小的质数以获得所需的差。 示例 以下是

  • 我写了一个程序,将数字分解为它的质因数,然后将它们存储在一个向量中,最后询问是否通过将它们相乘来验证结果。 它的工作方式是这样的:要求一个数字(代码中的),然后将其除以2及以上。 如果它找到一个模(当mod时)为零的数字(代码中的 ),则将该除数存储到一个向量中,并将其除以 ,然后将其存储到 中,然后将除数重置为1(而 循环中的最后一条语句将其递增为2)。如果没有找到这样的数字, 将增加,直到它大

  • 我正在尝试自动查找一个数字与另一个数字的最接近因子; 示例: 700到30的最接近因子是28(30不等于700,但28等于700)。 一个显而易见的解决方案就是得到700的所有因子,并做一个简单的距离计算,找到离30最近的因子,但这似乎是低效的。 另一种解决方案是找到所有基本质因数,例如: 将这些数字相乘得到所有的组合,从而找到最接近的。 我正在尝试对其进行编程,使其自动化。有更好的解决方案吗?

  • 我有一些用于Euler项目的代码。求最大素因子600851475143。这需要很长时间才能完成,至少需要30分钟。你们能看出来是因为我的代码太长了,还是我的代码错了。还有,有什么让运行时间更快的提示吗?

  • 所以我想找到关于欧拉计划的问题3的答案。我需要确定给定数的最大素数因子。 引述欧拉项目:“13195的素数因子是5、7、13和29。600851475143中最大的素数因子是什么?” 我已经构建了我的代码,它在任何int大小的东西上都能完美地工作。但是由于它们给出的巨大数字,我的代码存在转换问题。 起初,我尝试切换到长变量和长数组,但我得到了错误:“可能从long到int的有损转换” 那么,我如何