【发布时间】:2019-01-17 11:39:25
【问题描述】:
#include<iostream>
using namespace std;
int gcd(int a, int b, int res);
int main()
{
int res = 1;
int n, i, ret;
int count = 1;
cin >> n;
for (i = 2; i < n; i++)
{
ret = gcd(n, i, res);
if (ret == 1)
count++;
}
cout << count;
return 0;
}
int gcd(int a, int b, int res)
{
if (a == b)
return res * a;
else if ((a % 2 == 0) && (b % 2 == 0))
return gcd(a / 2, b / 2, 2 * res);
else if (a % 2 == 0)
return gcd(a / 2, b, res);
else if (b % 2 == 0)
return gcd(a, b / 2, res);
else if (a > b)
return gcd(a - b, b, res);
else
return gcd(a, b - a, res);
}
请解释我需要纠正什么,比如我可以使用 scanf 而不是 cin? 另一个条件是:- 输入的唯一行是一个整数 N,它不能被任何大于 13 的素数整除。这种情况会影响我的 TLE 吗?
实际问题是:
倒数 问题描述 每个人都知道乘法 mod n,其中 n 是一个正整数。两个正整数 a 和 b mod n 的乘积是乘积除以 n 的余数。
如果有一个小于 n 的正整数 x 使得 a 和 x mod n 的乘积为 1,则称 a 与 n 有乘法逆元。
伟大的数学家欧拉证明了每一个小于 n 且与 n 互质的正整数(没有除 1 以外的 n 的公因数)关于 n 的乘法逆。
这个问题是找到小于n的正整数的个数,这些正整数与n有乘法逆元
约束 N
输入格式 输入的唯一行是一个整数 N,它不能被任何大于 13 的素数整除。
输出 一行包含一个整数,给出小于 N 且具有乘法逆元的整数个数
解释 示例 1
输入
20
输出
8
解释
N=20
如果我们列出小于 20 且除 1 之外与 20 没有公因数的数,它们是
1、3、7、9、11、13、17、19
因为它们有 8 个,所以有 8 个小于 20 的数与 20 有乘法逆元。因此结果是 8。
示例 2
输入
36
输出
12
解释
N=36。有 12 个小于 36 的数除了 1 和 36 之外没有公因数。这些是
1、5、7、11、13、17、19、23、25、29、31、35
因此,正如 Euler 所证明的,有 12 个小于 36 的数与 36 有乘法逆元。因此输出为 12。 https://i.stack.imgur.com/cvM0l.png
【问题讨论】:
-
我可以使用 scanf 代替 cin? 这通常不会修复 TLE。 TLE 通常是因为您的算法太慢了。您的输入是否需要多几微秒才能读取并不重要。
-
不要费心使用 C I/O。与普遍的看法相反,它并不比
cin和cout快,特别是如果您禁用与stdio的同步并且您只读取一个整数。你的算法太慢了,但如果我们不知道你在做什么,我们很难帮助你改进它。 -
“我的算法需要 O(logn) 时间复杂度。” 和
for (i = 2; i < n; i++)矛盾。 -
关于我的算法需要 O(logn) 时间复杂度,我建议在
gcd中弹出一个计数器并测试该断言。 -
我非常怀疑
O(log n)算法是否会 TLE。如果您的算法使用类似10 * log2(n)的操作,n必须是类似 2^50000000 的操作,才能总共进行 5 亿次操作,这是您的普通计算机在一秒钟内可以完成的操作(实际数字可能更多)。另一种思考方式是,log2(10^9)大约是 30,如前所述,计算机每秒至少可以执行 5 亿次操作。
标签: c++