lightoj1336——打表找规律(唯一分解定理)

题目链接: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;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Sigma函数是指一个数字的所有因子之和。给定一个数字n,需要求出有多少个数字的Sigma函数是偶数。\[2\] 为了解决这个问题,可以先筛选出n范围内的素数(范围在10^6即可),然后对n进行素因子分解。对于每个因子,如果它的Sigma函数中连乘的每一项都是偶数,那么整个Sigma函数就是偶数。具体实现中,可以判断每个因子的平方根是否为偶数,如果是偶数,则减去(平方根+1)/2。\[1\] 另外,还可以使用O(1)的做法来解决这个问题。根据观察,所有的完全平方数及其两倍的值都会导致Sigma函数为偶数。因此,可以直接计算n的平方根,然后减去(平方根+1)/2即可得到结果。\[3\] #### 引用[.reference_title] - *1* [Sigma Function](https://blog.csdn.net/PNAN222/article/details/50938232)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [【LightOJ1336】Sigma Function(数论)](https://blog.csdn.net/qq_30974369/article/details/79009498)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值