题目链接:http://lightoj.com/volume_showproblem.php?problem=1336
Sigma function is an interesting function in Number Theory. It is denoted by the Greek letter Sigma (σ). This function actually denotes the sum of all divisors of a number. For example σ(24) = 1+2+3+4+6+8+12+24=60. Sigma of small numbers is easy to find but for large numbers it is very difficult to find in a straight forward way. But mathematicians have discovered a formula to find sigma. If the prime power decomposition of an integer is
Then we can write,
For some n the value of σ(n) is odd and for others it is even. Given a value n, you will have to find how many integers from 1 to n have even value of σ.
Input
Input starts with an integer T (≤ 100), denoting the number of test cases.
Each case starts with a line containing an integer n (1 ≤ n ≤ 1012).
Output
For each case, print the case number and the result.
Sample Input
4
3
10
100
1000
Sample Output
Case 1: 1
Case 2: 5
Case 3: 83
Case 4: 947
题目翻译:
求和运算是一种有趣的操作,它来源于古希腊字母σ,现在我们来求一个数字的所有因子之和。例如σ(24)=1+2+3+4+6+8+12+24=60.对于小的数字求和是非常的简单,但是对于大数字求和就比较困难了。现在给你一个n,你需要求出有多少个[ 1 , n ]区间内的数字σ是偶数。
注:一个数字的σ指这个数的所有因子之和
Input
输入包含T(T<=100)组数据,每一组只有一个数字n(1<=n<=10^12)
Output
输出样例号和一个数字,为所求答案。注意!两组输出之前没有空行。
唯一分解定理,不过是用来打表找规律的,不用想,如果直接暴力的话肯定会超时,1e12的范围还是很大的。
所以只能换一种思路来想,首先我们可以打表求出1到100内所有不符合的数(下面转自规律)。
那么我们可以通过超时的代码将100中不满足的数打出来,如下:
1
2
4
8
9
16
18
25
32
36
49
50
64
72
81
98
100
发现100中,因子和为奇数的有:
1 2 4 8 9 16 18 25 32 36 49 50 64 72 81 98 100
有没有发现,这些数字有一个规律,他们是 x^2, 2*x, 2*x^2, 只要100中的数满足这三个中的一个,那么,这个数就是不满足的,
总数-不满足的个数 = 满足的个数
我们还可以发现:当x为偶数时2*x和x^2会有重复的部分
当x为奇数时2*x和2*x^2会有重复的部分
那么我们可以将2*x省去,我们求求出x^2的个数和2*x^2的个数,然后用总数减去它们的个数即可
然后直接输出结果就行了。
#include<iostream>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const int N = 100000 + 5;
bool visited[N];//visited[i]表示i是不是质数
int prime[N], tot;//prime[N]用来存质数
void init(){
for(int i = 2; i < N; i ++) visited[i] = true;//初始化为质数
for(int i = 2; i < N; i++){
if(visited[i]) prime[tot ++] = i;//把质数存起来
for(int j = 0; j < tot && i * prime[j] < N; j++){
visited[i * prime[j]] = false;
if(i % prime[j] == 0) break;//保证每个合数被它最小的质因数筛去
}
}
}
ll sigma(ll n){
ll s=1;
for(ll i=0;prime[i]*prime[i]<=n&&i<tot;++i){
if(n%prime[i]==0){
ll a=1;
while(n%prime[i]==0){
n/=prime[i];
a*=prime[i];
}
s*=(a*prime[i]-1)/(prime[i]-1);
}
}
if(n>1) s=s*(1+n);
return s;
}
int main(){
int T;
ll n;
scanf("%d",&T);
init();
for(int kcase=1;kcase<=T;kcase++){
scanf("%lld",&n);
// for(ll i=1;i<=n;++i){
// if(sigma(i)%2!=0){
// printf("%lld\n",i);
// }
// }
printf("Case %d: %lld\n",kcase,n-(ll)sqrt(n)-(ll)sqrt(n/2.0));
}
return 0;
}