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

题目描述

  神炎皇乌利亚很喜欢数对,他想找到神奇的数对。
  对于一个整数对$(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++

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

时间: 2024-08-30 13:23:39

[CSP-S模拟测试]:神炎皇(数学)的相关文章

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

神炎皇: 题意: 对于一个整数对$(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$. 又由(

【NOIP2017提高组模拟12.10】神炎皇

题目 神炎皇乌利亚很喜欢数对,他想找到神奇的数对. 对于一个整数对(a,b),若满足a+b<=n且a+b是ab的因子,则成为神奇的数对.请问这样的数对共有多少呢? 分析 设\(gcd(a,b)=d,a'd=a,b'd=b\) 那么\(a'+b'|a'b'd\) 因为\(gcd(a',b')=1\) 所以\(a'+b'|d\). 又因为\((a'+b')d<=n\) 则\(a'+b'=\sqrt n\) 枚举\(a'+b'=i\) \(d就有\dfrac{n}{i^2}种情况\) 因为\(gcd

[CSP-S模拟测试]:画作(BFS+数学)

题目描述 小$G$的喜欢作画,尤其喜欢仅使用黑白两色作画.画作可以抽象成一个$r\times c$大小的$01$矩阵.现在小$G$构思好了了他的画作,准备动笔开始作画.初始时画布是全白的,他每一次下笔可以将一个四联通的部分涂成黑色或白色.你需要告诉他,在给出的构思下,他最少需要下笔多少次才能完成画作. 输入格式 第一行两个正整数$r,c$.接下来$r$行,每行$c$个字符,表示目标画作. 输出格式 输出一行一个正整数,表示最少需要的下笔步数. 样例 样例输入: 3 3010101010 样例输出

[CSP-S模拟测试]:排列组合(数学 or 找规律)

题目描述 $T$组数据,每次给定$n$,请求出下式的值,对$10^9+7$取模: $$C_n^0\times C_n^0+C_n^1\times C_n^1+C_n^2\times C_n^2+...+C_n^n\times C_n^n$$ 输入格式 第一行一个整数$T$,表示数据组数.接下来$T$行,每一行包含一个整数$n$,含义如题所示. 输出格式 输出$T$行,每行包含一个整数,表示对$10^9+7$取模后的答案. 样例 样例输入: 212 样例输出: 26 数据范围与提示 对于$30\%

[CSP-S模拟测试]:异或(数学)

题目描述 给定$L,R$,我们希望你求出:$$\sum\limits_{i=L}^R\sum\limits_{j=L}^R(i\oplus j)$$其中这里的$\oplus$表示异或运算.答案对$10^9+7$取模. 输入格式 第一行一个整数$T$,表示数据组数.接下来$T$行,每行两个整数$L,R(0\leqslant L\leqslant R\leqslant 10^9)$,描述一组数据. 输出格式 每组数据输出一行一个整数,表示答案. 样例 样例输入: 21 20 1023 样例输出: 6

[CSP-S模拟测试]:平方数(数学+哈希)

题目传送门(内部题137) 输入格式 第一行,一个正整数$n$. 第二行$n$个正整数$a_1\sim a_n$. 输出格式 输出一个整数,为满足条件的二元组个数. 样例 样例输入: 51 2 3 4 12 样例输出: 2 数据范围与提示 对于$20\%$的数据,满足$n\leqslant 3,000$. 对于$50\%$的数据,满足$n\leqslant 50,000$. 对于另$20\%$的数据,满足$a_i\leqslant 1,000$. 对于$100\%$的数据,满足$1\leqsla

[考试反思]1010csp-s模拟测试67:摸索

嗯...所谓RP守恒? 仍然延续着好一场烂一场的规律. 虽说我也想打破这个规律,但是并不想在考烂之后打破这个规律.(因为下一场要考好???) 我也不知道我现在是什么状态,相较于前一阶段有所提升(第一鸡房的buff?) 但是明显还有提升空间.也可以看到离上面的差距有多大. (在去食堂的路上一顿爆捶捶傻skyh就能进步一名了hhh) 这场考试呢,T1正路是推式子然而我又开始疯狂打表找规律,最后得到了一个和正解没什么关系但是能拿到80分的式子. 也肝了一个小时,然后就停止在80分了. 并不是没有在化式

csp-s模拟测试70

发现不码题解还是记不清题. A. 木板 枚举$y_E$,求出$x_F$关于$y_E$的式子,设$y_E$为$x$,发现$Ans=\sum\limits_{x=1}^{n-1} [n|x^2]$ 考场上受<神炎皇>启发,提出$gcd$,设$gcd(x,n)=d$ $n'd|x'^2d^2$ $n'|x'^2d$ 又因为$gcd(n',x')=1$ 所以$gcd(n',x'^2)=1$ 就有$n'|d$ 设$kn'=d$ 联立$n'd=n$ 得$kn'^2=n$ 所以有$n' \leq \sqrt

模拟测试(vj)

做这份模拟测试,已经崩溃了,英文看不懂,题意理解错.到结束了只a了第一题,人生陷入了低谷,于是花了一天的时间终于把不会的弄明白了,在这里写一份总结~ T1,简单的模拟,如果打枪打中一支鸟,将这个位置设为0,并向两边扩散,注意这个位置一定要有鸟. 代码~ #include<bits/stdc++.h> using namespace std; int a[30000]; int n,m; int main() { cin>>n; for(int i=1;i<=n;i++) ci