题目:http://www.lightoj.com/volume_showproblem.php?problem=1007
题意:对于数x,定义score(x) = n^2,n是1~x中与x互质的数的个数。然后求a~b之间所有数的score()之和
思路:欧拉函数,很裸了,但结果会溢出,用long long也会溢出,用unsigned long long才可以,然后输出格式控制用%llu。。。
定义法欧拉函数:
int euler(int n)
{
int res = n;
int m = (int)sqrt(n);
for(int i = 2; i <= m; i++)
if(n % i == 0)
{
res = res / i * (i-1);
while(n % i == 0) n /= i;
}
if(n > 1) res = res / n * (n-1);
return res;
}
筛选法求欧拉函数
void euler()
{
for(int i = 1; i < N; i++) arr[i] = i;
for(int i = 2; i < N; i++)
if(arr[i] == i)
for(int j = i; j < N; j += i) //j要从i开始,这样可以处理素数的情况
arr[j] = arr[j] / i * (i-1);
}
本题代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ll;
const int N = 5000100;
ll arr[N];
int cas;
void euler()
{
for(int i = 1; i < N; i++) arr[i] = i;
for(int i = 2; i < N; i++)
if(arr[i] == i)
for(int j = i; j < N; j += i)
arr[j] = arr[j] / i * (i-1);
}
int main()
{
int t, a, b;
euler();
for(int i = 1; i < N; i++) arr[i] = arr[i-1] + arr[i] * arr[i];
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &a, &b);
printf("Case %d: %llu\n", ++cas, arr[b] - arr[a-1]);
}
return 0;
}