您的位置:首页 > 其它

hdu 3501 Calculation 2

2012-10-28 21:22 225 查看
题目描述:求小于n且与n不互质的数的和。

分析:

  方法一:容斥原理。对n分解因式,利用容斥原理来n的因子的和即为答案。

  方法二:考虑欧拉函数,n之前与n互质的数的和sum=n*euler(n)/2

     如果gcd(n,i)=1,那么必有gcd(n,n-i)=1,所以与n互质的数应该是成对出现的,每一对的和就是n,所以总和就是n*euler(n)/2;

容斥原理解法

#include<iostream>
#include<cstring>
#include<vector>
#define N 1000010
using namespace std;
typedef long long ll;
const ll mod=1000000007;
bool p
;
ll s
;
vector<ll>x;
void init(){
memset(p,1,sizeof(p));
for(int i=2;i*i<N;i++)
for(int j=i;i*j<N;j++)
p[i*j]=0;
s[0]=0;
for(int i=2;i<N;i++)
if(p[i])s[++s[0]]=i;
}
void div(ll n){
x.clear();
for(int i=1;s[i]*s[i]<=n;i++){
if(n%s[i]==0){
x.push_back(s[i]);
while(n%s[i]==0)n/=s[i];
}
}
if(n>1)x.push_back(n);
}
ll cal(ll a,ll n){
return (n/a)*(n-a)/2;
}
void solve(ll n){
div(n);
ll ans=0;
int c=x.size();
for(int i=1;i<(1<<c);i++){
int cnt=0,a=0,ii=i;
ll num=1;
while(ii>0){
if(ii&1){
num*=x[cnt];
++a;
}
ii>>=1;
++cnt;
}
ll count=cal(num,n);
if(a&1)ans=(ans+count);
else ans=(ans-count);
}
cout<<ans%mod<<endl;
}
int main(){
init();
ll n;
while(cin>>n){
if(!n)return 0;
solve(n);
}
return 0;
}


欧拉函数解法

#include<iostream>
#include<cstring>
#define N 1000010
using namespace std;
typedef long long ll;
const ll mod=1000000007;
bool p
;
ll s
;
void init(){
memset(p,1,sizeof(p));
for(int i=2;i*i<N;i++)
for(int j=i;i*j<N;j++)
p[i*j]=0;
s[0]=0;
for(int i=2;i<N;i++)
if(p[i])s[++s[0]]=i;
}
ll euler(ll n){
ll ans=n;
for(int i=1;s[i]*s[i]<=n;i++){
if(n%s[i]==0){
ans/=s[i];
ans*=(s[i]-1);
while(n%s[i]==0)n/=s[i];
}
}
if(n>1){
ans/=n;
ans*=(n-1);
}
return ans;
}
int main(){
init();
ll n;
while(cin>>n){
if(!n)return 0;
ll ans=n*(n-1)/2;
cout<<(ans-euler(n)*n/2)%mod<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: