问题的链接是 - spoj question
我试过通过这种方法解决问题 - N范围内的对数= N-1范围内的对数+一些新对。
但我不知道还应该在这里做什么优化来避免TLE。我也读过有关euler totient函数的内容,但我不能真正理解这种方法。我猜我已经阅读了4种计算euler phi的方法,但都需要相同的O(n ^ 2)。
P.S - 我想知道关于进一步的方法应该是什么,而不是直接的解决方案。提示会做。 非常感谢提前。
我对这个问题的代码是 -
#include<stdio.h>
typedef unsigned long long int ull;
ull a[100000] = {0};
inline ull g()
{
ull n=0;
char ch;
ch = getchar_unlocked();
while(ch < '0' || ch > '9')
ch = getchar_unlocked();
while(ch >= '0' && ch <= '9') {
n = (n<<3) + (n<<1) + (ch - '0');
ch = getchar_unlocked();
}
return n;
}
ull gcd( ull a , ull b)
{
if(b == 0)
return a;
else
return gcd(b , a % b);
}
ull find(ull n)
{
if(n == 0 || n == 1)
return n;
else if(a[n] != 0)
return n;
else
return find(n-1);
}
ull range(ull n)
{
ull c, i, nf,t;
nf = find(n);
c = a[nf];
t = nf;
nf++;
while(nf <= n) {
a[nf] = a[t];
for(i = 2 ; i <= nf ; i++) {
ull gd = gcd(i,nf);
if(gd > 1) {
c++;
a[nf]++;
}
}
nf++;
}
return c;
}
int main()
{
ull t = g();
ull i = 1;
while(t--) {
ull n = g();
if(a[n] == 0)
a[n] = range(n);
printf("Case %llu: %llu\n",i++,a[n]);
}
return 0;
}
答案 0 :(得分:0)
只是去尝试并获得AC。
正如你所说的那样,这里有一些基于我的AC解决方案和你的尝试:
bonus
?真?至少在我的代码中,我不认为它是O(n^2)
O(n^2)
功能不需要GCD
的循环,你可以在n
输出答案!答案 1 :(得分:0)
嗯,我认为一个更好的方法是根据Euler的Totient函数来考虑...... Totient函数给出了数字n以下的数字的数量,即与它共同的,即GCD(n,x)= 1其中
x&lt; n。
现在直到n的对是对,直到n-1 +对为n,即(n的n-幂函数)。
对于Totient函数,请参阅Link
我认为你需要在Totient Sieve的帮助下预处理每个数字的总数直到10 ^ 6,因为N * Root(N)不会及时通过。