题意:
sigma(n)=n的所有因子之和,例如sigma(24) = 1+2+3+4+6+8+12+24=60,求1-n内有多少sigma函数的值为偶数。
思路:
从测试数据可以看出为偶数的情况比较多,所以可以反过来对奇数的情况进行讨论。
从上述公式能够看得出sigma函数的值可以通过分解n的素因子得到。
而对于上述公式可以有如下分析:
1.对于唯一的偶素数2,(2^n-1) / (2-1) 恒为奇数。
2.对于其他素数的(p^n-1) / (p-1)如何进行分析呢?
n=1 ----------> (p-1)/(p-1)=1
1为奇数。
n=2 ----------> (p^2-1)(p-1)=(p+1)(p-1)/(p-1)=p+1(平方差公式)
因为p一定为奇数 所以p+1为偶数
n=3 ----------> (p^3-1)/(p-1)=(p^2+p+1)(p-1)/(p-1)=p^2+p+1(立方差公式)
p^2+p+1,三个奇数相加,结果为奇数
n=4 ----------> (p^4-1)/(p-1)=(p^3+p^2+p+1)(p-1)/(p-1)=p^3+p^2+p+1(四次方差公式)
p^3+p^2+p+1,四个奇数相加,结果为偶数
因为每次化简后通过n次方差公式可以将该素因子对应的项化为∑p^(n-1)。并且每一项都为奇数,所以该素因子的对应项的奇偶性与n-1的奇偶性一致。
所以当n中有偶数个该素因子时可以保证该项为奇数,当所有除2以外的素因子都有偶数个时,可以保证sigma(n)为奇数(奇数相乘结果为奇数)。反之,有一个除2以外的素因子有奇数个,sigma(n)则为偶数。
3.因此sigma(n)为奇数的n都可以表示为(2^e)*(c^2) c为奇数,e为任意正整数。
代码实现如下:
#include <iostream>
#include <stdio.h>
#include <math.h>
using namespace std;
long long ds[100];
const long long MAXN=1000000000005;
int solve()
{
int cnt=1;
ds[0]=1;
while(1)
{
ds[cnt]=ds[cnt-1]*2;
//cout<<ds[cnt]<<endl;
if(ds[cnt]>MAXN) break;
cnt++;
}
return cnt;
}
int main()
{
int T,c=1;
long long n;
int lim=solve();
scanf("%d",&T);
while(T--)
{
scanf("%lld",&n);
long long ans=0;
for(int i=0;i<lim;i++)
{
if(ds[i]>n) break;
//cout<<ans<<endl;
ans+=((long long)sqrt((n/ds[i])+0.5)+1)/2;
}
printf("Case %d: %lld\n",c++,n-ans);
}
return 0;
}