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)为奇数的数然后二分查一下
当然有更简单的做法。
当sigma(n)为奇数时,n满足
n=2k∗p12a1∗p22a2∗....∗pt2at
即,n要么是2倍的完全平方数,要么是完全平方数
容斥一下即可
ans=n-floor(sqrt(n))-floor(sqrt(n/2));
定义了一个函数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));