20160317 Uva11395 Sigma Function(素因子分解+各种公式+筛数)

题意:
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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值