您的位置:首页 > 其它

lightoj1336Sigma Function(dfs打表或容斥)

2016-05-03 03:16 453 查看
题目链接:http://lightoj.com/volume_showproblem.php?problem=1336

定义了一个函数sigma(n),它的值为n的约数和,求n以内sigma(i)为偶数的个数

那么如果

n=p1a1∗p2a2.....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 1000000
using 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=2k∗p12a1∗p22a2∗....∗pt2at

即,n要么是2倍的完全平方数,要么是完全平方数

容斥一下即可

ans=n-floor(sqrt(n))-floor(sqrt(n/2));
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  lightoj 数学