Mathematically some problems look hard. But with the help of the computer, some problems can be easily solvable.
In this problem, you will be given two integers a and b. You have to find the summation of the scores of the numbers from a to b (inclusive). The score of a number is defined as the following function.
score (x) = n2, where n is the number of relatively prime numbers with x, which are smaller than x
For example,
For 6, the relatively prime numbers with 6 are 1 and 5. So, score (6) = 22 = 4.
For 8, the relatively prime numbers with 8 are 1, 3, 5 and 7. So, score (8) = 42 = 16.
Now you have to solve this task.
Input
Input starts with an integer T (≤ 105), denoting the number of test cases.
Each case will contain two integers a and b (2 ≤ a ≤ b ≤ 5 * 106
Output
For each case, print the case number and the summation of all the scores from a to b.
Sample Input
3
6 6
8 8
2 20
Sample Output
Case 1: 4
Case 2: 16
Case 3: 1237
Note
Euler's totient function applied to a positive integer n is defined to be the number of positive integers less than or equal to n that are relatively prime to n. is read "phi of n."
Given the general prime factorization of , one can compute using the formula
这一题说简单也简单,但是在这之前必须了解什么是欧拉函数,
欧拉函数就是指一个数和比它小的数互质的有多少(包括1)。
比如7:它是一个质数,所以它前面的数都和它互质,故dp[7]=6;
比如9: 3和6都和它有约数,故它dp[9]=8-2=6;
再来说说这一题,给出的这两个数a,b是干嘛的呢?
我用式子写一下,就是求 dp[b]*dp[b]-dp[a-1]*dp[a-1];
这下看懂了吧。^_^
欧拉函数的模板如下
void Euler()
{
memset(phi,0,sizeof(phi));
phi[1]=1;
for(int i=2;i<N;i++)
{
if(!phi[i])
{
for(int j=i;j<N;j+=i)
{
if(!phi[j])
phi[j]=j;
phi[j]=phi[j]/i*(i-1);
}
}
}
}
还有一个据说更快,但是我还没记住,
/*
特性 :
1.若a为质数,phi[a]=a-1;
2.若a为质数,b mod a=0,phi[a*b]=phi[b]*a
3.若a,b互质,phi[a*b]=phi[a]*phi[b](当a为质数时,if b mod a!=0 ,phi[a*b]=phi[a]*phi[b])
*/
int m[n],phi[n],p[n],nump;
//m[i]标记i是否为素数,0为素数,1不为素数;p是存放素数的数组;nump是当前素数个数;phi[i]为欧拉函数
int main()
{
phi[1]=1;
for (int i=2;i<=n;i++)
{
if (!m[i])//i为素数
{
p[++nump]=i;//将i加入素数数组p中
phi[i]=i-1;//因为i是素数,由特性得知
}
for (int j=1;j<=nump&&p[j]*i<=n;j++) //用当前已得到的素数数组p筛,筛去p[j]*i
{
m[p[j]*i]=1;//可以确定i*p[j]不是素数
if (i%p[j]==0) //看p[j]是否是i的约数,因为素数p[j],等于判断i和p[j]是否互质
{
phi[p[j]*i]=phi[i]*p[j]; //特性2
break;
}
else phi[p[j]*i]=phi[i]*(p[j]-1); //互质,特性3其,p[j]-1就是phi[p[j]]
}
}
}
//来自百度百科
本题代码如下:
#include<stdio.h>
#include<string.h>
typedef unsigned long long ll;
const int N=5000010;
ll dp[N];
void init()
{
memset(dp,0,sizeof(dp));
dp[1]=1;
for(int i=2;i<N;i++)
{
if(dp[i])
continue;
for(int j=i;j<N;j+=i)
{
if(!dp[j])
dp[j]=j;
dp[j]=dp[j]/i*(i-1);
}
}
ll num=0;
for(int i=1;i<N;i++)
{
num+=dp[i]*dp[i];
dp[i]=num;
}
}
int main()
{
init();
int T,num=1,a,b;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&a,&b);
printf("Case %d: ",num++);
printf("%llu\n",dp[b]-dp[a-1]);
}
return 0;
}