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

[CSP-S模拟测试]:神炎皇(数学)

时间:2019-10-10 22:04:35      阅读:120      评论:0      收藏:0      [点我收藏+]

标签:枚举   时间   size   情况   格式   输出   com   scan   font   

题目描述

  神炎皇乌利亚很喜欢数对,他想找到神奇的数对。
  对于一个整数对$(a,b)$,若满足$a+b\leqslant n$且$a+b$是$ab$的因子,则称为神奇的数对。请问这样的数对共有多少呢?


输入格式

一行一个整数$n$。


输出格式

一行一个整数表示答案,保证不超过$64$位整数范围。


样例

样例输入:

21

样例输出:

11


数据范围与提示

对于$20\%$的数据,$n\leqslant 1000$;
对于$40\%$的数据,$n\leqslant 100000$;
对于$60\%$的数据,$n\leqslant 10000000$;
对于$80\%$的数据,$n\leqslant 1000000000000$;
对于$100\%$的数据,$n\leqslant 100000000000000$。


题解

总是喜欢在考场上刚数学题,总是刚不出来,总是就差一步……

不妨设一个神奇的数对$(a,b)$,$d=gcd(a,b)$,$a‘=\frac{a}{d}$,$b‘=\frac{b}{d}$。

我们要满足$(a+b)|ab$($|$为整除),也就是要满足$(a‘+b‘)d|(a‘b‘)d^2$

消去一个$d$,则我们可以得到$(a‘+b‘)|(a‘b‘)d$。

又$\because gcd(a‘,b‘)=1$,根据辗转相除法还可以得到$(a‘+b‘,a‘)=(a‘+b‘,b‘)=1$(手打$gcd$的方法),$\therefore gcd(a‘+b‘,a‘b‘)=1$。

也就是说$(a‘+b‘)$一定不是$a‘b‘$的因子,那么其只能是$d$的因子,则条件转化为求$(a‘+b‘)|d$。

不妨设$m=(a‘+b‘),d=km$,则$km^2\leqslant n$。

而$m$只用枚举到$\sqrt{n}$即可。

发现对于每一个$m$,$k$有$\left\lfloor\frac{n}{m^2}\right\rfloor$种不同的解。

接下来考虑$m$的内部情况,接着利用辗转相除法,可以得到其个数为$\phi(i)$,于是答案就是:

$$\sum \limits_{i=1}^n \phi(i)\left\lfloor\frac{n}{m^2}\right\rfloor$$

时间复杂度:$\Theta(\sqrt{n})$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
long long n;
long long ans;
int phi[10000001],prime[10000001];
bool vis[10000001];
int main()
{
	scanf("%lld",&n);
	int sqr=sqrt(n);
	phi[1]=1;
	for(int i=2;i<=sqr;i++)
	{
		if(!vis[i])
		{
			vis[i]=1;
			prime[++prime[0]]=i;
			phi[i]=i-1;
		}
		for(int j=1;j<=prime[0]&&i*prime[j]<=sqr;j++)
		{
			vis[i*prime[j]]=1;
			if(i%prime[j])phi[i*prime[j]]=phi[i]*(prime[j]-1);
			else{phi[i*prime[j]]=phi[i]*prime[j];break;}
		}
		ans+=1LL*phi[i]*(n/i/i);
	}
	printf("%lld",ans);
	return 0;
}

rp++

[CSP-S模拟测试]:神炎皇(数学)

标签:枚举   时间   size   情况   格式   输出   com   scan   font   

原文地址:https://www.cnblogs.com/wzc521/p/11650824.html

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