hdu 3501 Calculation 2

来源:互联网 发布:mysql 自定义排序 编辑:程序博客网 时间:2024/04/26 06:04

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3501&PHPSESSID=r6neeegb0ieth2634frpqg4rb5


题目大意:

给一个数n(1~10^9),求所有小于n且和n不互质的数的和。


题目思路:

(1)很容易想到求出n的所有素因子,设x为n的素因子,那么所有满足条件的数且含有约数x的个数为n/x-1那么和即为x*(1+n/x-1)*(n/x-1)/2

但是如果y也会n的素因子,那么就会就会重复计算所有满足条件的数且含有约数x*y

显然到了这边,可以看出是移到容斥题了。

(2)还有一种比较巧妙的方法,就是利用欧拉函数。

因为如果x和n互质,那么n-x也和n互质,所以所有互质数的和的平均数为n/2,所以得到公式。

Result = (1+n)*n/2 - eular(n)*n/2

eular(n):求n的互质数个数。


代码:

#include <stdlib.h>#include <string.h>#include <stdio.h>#include <ctype.h>#include <math.h>#include <stack>#include <queue>#include <map>#include <set>#include <vector>#include <string>#include <iostream>#include <algorithm>using namespace std;#define ll __int64#define ls rt<<1#define rs ls|1#define lson l,mid,ls#define rson mid+1,r,rs#define middle (l+r)>>1#define clr_all(x,c) memset(x,c,sizeof(x))#define clr(x,c,n) memset(x,c,sizeof(x[0])*(n+1))#define eps (1e-8)#define MOD 1000000007#define INF 0x3f3f3f3f#define PI (acos(-1.0))#pragma comment(linker, "/STACK:102400000,102400000")template <class T> T _max(T x,T y){return x>y? x:y;}template <class T> T _min(T x,T y){return x<y? x:y;}template <class T> T _abs(T x){return (x < 0)? -x:x;}template <class T> T _mod(T x,T y){return (x > 0)? x%y:((x%y)+y)%y;}template <class T> void _swap(T &x,T &y){T t=x;x=y;y=t;}template <class T> void getmax(T& x,T y){x=(y > x)? y:x;}template <class T> void getmin(T& x,T y){x=(x<0 || y<x)? y:x;}int TS,cas=1;const int M=100000+5;int n,f[M],tot;ll dfs(int pos,int sum){if(pos==tot) return 0;ll cnt=(n/sum-1),ret=(1+cnt)*cnt/2*sum;for(int i=pos+1;i<=tot;i++)ret=((ret-dfs(i,sum*f[i]))+MOD)%MOD;return ret;}void run(){int i,j;int nn=n;for(i=2,tot=0;i*i<=nn;i++) if(nn%i==0){while(nn%i==0) nn/=i;f[tot++]=i;}if(nn>1) f[tot++]=nn;ll ret=0;for(i=0;i<tot;i++)ret=(ret+dfs(i,f[i]))%MOD;printf("%I64d\n",ret);}void preSof(){}int main(){    //freopen("input.txt","r",stdin);    //freopen("output.txt","w",stdout);    preSof();    //run();    while((~scanf("%d",&n)),n) run();    //for(scanf("%d",&TS);cas<=TS;cas++) run();    return 0;}


原创粉丝点击