lightoj1336Sigma Function(dfs打表或容斥)

来源:互联网 发布:淘宝加盟的骗局揭秘 编辑:程序博客网 时间:2024/05/01 03:23

题目链接:http://lightoj.com/volume_showproblem.php?problem=1336
定义了一个函数sigma(n),它的值为n的约数和,求n以内sigma(i)为偶数的个数
那么如果
n=p1a1p2a2.....ptat
sigma(n)=(p10+p11+...+p1a1)(p20+p21+...+p2a2)...(pt0+pt1+...+ptat)
把每个括号内看成一项,则每项都为奇数sigma(n)才为奇数
1.p=2时,其所在项一定为奇数。
2.ai为偶数时,其所在项一定为奇数。
那么可以先打表找出所有sigma(i)为奇数的数然后二分查一下

#include <stdio.h>#include<iostream>#include<cmath>#include<cstring>#include<algorithm>#define Max 1000000using namespace std;typedef long long LL;const LL mx=1000000000000LL;bool is[Max+10];LL pri[100000];LL odd[2000000];int siz=0;int siz2=0;void init(){    memset(is,0,sizeof(is));    for(LL i=2;i<=Max;i++){        if(!is[i])pri[++siz]=i;        for(int j=1;j<=siz&&pri[j]*i<=Max;j++){            is[pri[j]*i]=1;            if(!(i%pri[j]))break;        }    }}void dfs(int pp,LL nw){    odd[++siz2]=nw;    for(int i=pp;i<=siz;i++){        LL tt=1;        if(i!=1)tt*=pri[i];        if(nw*tt>mx)return;        tt*=pri[i];        if(nw*tt>mx)return;        dfs(i,nw*tt);    }}int main(void){    init();    dfs(1,1);    sort(odd+1,odd+1+siz2);    int t,cas=0;    scanf("%d",&t);    while(t--){        LL n;        scanf("%lld",&n);        int ans=upper_bound(odd+1,odd+1+siz2,n)-odd-1;        printf("Case %d: %lld\n",++cas,n-ans);    }    return 0;}

当然有更简单的做法。
当sigma(n)为奇数时,n满足
n=2kp12a1p22a2....pt2at
即,n要么是2倍的完全平方数,要么是完全平方数
容斥一下即可
ans=n-floor(sqrt(n))-floor(sqrt(n/2));

0 0
原创粉丝点击