的主要挑戰是處理查詢(Q),其可以很大。 1 < = Q < =
方法我迄今使用:
蠻力
while(Q--)
{
int N;
cin>>N;
for(int i=1;i<=N;i++)
ans += lcm(i,N)/i ;
}
處理查詢
首先我建立一個表,它保存每個N的歐拉總功能值。 這可以在O(N)中完成。
void sieve()
{
// phi table holds euler totient function value
// lp holds the lowest prime factor for a number
// pr is a vector which contains prime numbers
phi[1]=1;
for(int i=2;i<=MAX;i++)
{
if(lp[i]==0)
{
lp[i]=i;
phi[i]=i-1;
pr.push_back(i);
}
else
{
if(lp[i]==lp[i/lp[i]])
phi[i] = phi[i/lp[i]]*lp[i];
else phi[i] = phi[i/lp[i]]*(lp[i]-1);
}
for(int j=0;j<(int)pr.size()&&pr[j]<=lp[i]&&i*pr[j]<=MAX;j++)
lp[i*pr[j]] = pr[j];
}
對於每個查詢分解N並將d*phi[d]
添加到結果中。
for(int i=1;i*i<=n;i++)
{
if(n%i==0)
{
// i is a factor
sum += (n/i)*phi[n/i];
if(i*i!=n)
{
// n/i is a factor too
sum += i*phi[i];
}
}
}
這需要O(sqrt(N))。
複雜度:O(Q * SQRT(N))
爲O處理的查詢(1)
爲了我以上I中描述的篩法添加,其計算我們需要在答案的一部分O(NLogN)
for(int i=1;i<=MAX;++i)
{
//MAX is 10^7
for(int j=i;j<=MAX;j+=i)
{
ans[j] += i*phi[i];
}
}
對於給定的約束條件和時間限制(1秒),不幸的是超時。
我認爲這涉及到關於N的素數因子分解的一些聰明的想法。 我可以使用上面構建的lp(最低主要)表格對O(LogN)中的數字進行因式分解,但我無法弄清楚如何使用因式分解法得出答案。
我想到了這一點。這裏的素數最大值可以是8('as 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 <= 10^7'),但不能將其轉換爲代碼。如何在這裏生成所有'j(j1,j2,j3等)'? 8個嵌套循環?!請你在這裏添加一些僞代碼。 – Alex
我加了一個僞代碼來計算這個總和。 –
您只能在遞歸調用中傳遞2個參數。另外'在m'鍵裏的pj這裏是什麼? – Alex