码迷,mamicode.com
首页 > 其他好文 > 详细

神炎皇(模拟测试67)(数论)

时间:2019-10-13 19:12:33      阅读:92      评论:0      收藏:0      [点我收藏+]

标签:var   cpp   答案   style   define   bool   ++   limit   header   

神炎皇:

  题意:

    对于一个整数对$(a,b)$,若满足$a+b<=n$且$a+b$是$a*b$的因子,则成为神奇的数对。请问这样的数对共有多少个?($N<=10^{14}$)

  题解:

    已知$a+b<=n\\ (a+b)|ab$。

    设$d=\gcd(a,b),x=a/d,y=b/d$。

    上式为$(x+y)*d<=n(1)\\ (x+y)|x*y*d(2)$。

    因为$\gcd(x+y,x)=\gcd(x+y,y)=\gcd(x,y)=1$。

    (2)式可化减为$(x+y)|d$。

    又由(1)式得$(x+y)<=\sqrt{n}$。

    设$k=x+y,d=z*k$,所以$z*k^2<=n$,那么合法的$d$的个数为$\lfloor \frac{n}{k^2} \rfloor$。

    而对于每一个$d$,都有$\varphi{k}$个$x$满足条件。

    所以最后答案为$\sum\limits_{i=1}^{\sqrt{n}} \varphi(i) * \lfloor \frac{n}{k^2} \rfloor$。

  code:

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define R register
#define ll long long
#define int long long
inline int read()
{
	int aa=0;char cc=getchar();
	while(cc<‘0‘||cc>‘9‘)cc=getchar();
	while(cc<=‘9‘&&cc>=‘0‘)
		aa=(aa<<3)+(aa<<1)+(cc^48),cc=getchar();
	return aa;
}
const int N=1e7+7,M=1e6;
int n,ans;bool mark[N];int tot,phi[N],prime[M];
void getphi(const int lim)
{
	for(R int i=2;i<=lim;++i){
		if(!mark[i])prime[++tot]=i,phi[i]=i-1;
		for(R int j=1;j<=tot;++j){
			if(i*prime[j]>lim)break;
			mark[i*prime[j]]=1;
			if(i%prime[j]==0){
				phi[i*prime[j]]=phi[i]*prime[j];break;
			}
			else phi[i*prime[j]]=phi[i]*(prime[j]-1);
		}
	}
}
signed main()
{
	//freopen("uria.in","r",stdin);
	//freopen("uria.out","w",stdout);
	n=read();
	const int lim=sqrt(n);
	getphi(lim+2);
	for(R int i=1;i<=lim;++i)
		ans+=phi[i]*(n/(i*i));
	printf("%lld",ans);
	return 0;
}
/*
21 
*/

 

 

 

神炎皇(模拟测试67)(数论)

标签:var   cpp   答案   style   define   bool   ++   limit   header   

原文地址:https://www.cnblogs.com/toot-wjh/p/11664120.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!