2020.01.30日常总结

我们两清 提交于 2020-01-31 11:21:16

P2568   GCD\color{green}{洛谷P2568\ \ \ GCD}

\color{blue}{【题意】:} 给定N(1N1×107)N(1 \leq N \leq 1 \times 10^7),求有多少对(x,y)(x,y)满足1x,yN1 \leq x,y \leq Ngcd(x,y)gcd(x,y)为素数(gcd(x,y)gcd(x,y)表示x,yx,y\color{red}{最大公约数})。

\color{blue}{【思路】:} 首先,我们求出1N1-N中的所有的素数,然后我们枚举gcd(x,y)gcd(x,y)。因为111×1071 \times 10^7的素数个数也不是很多,所以枚举也是很快的。

我们设gcd(x,y)=p,x=a×p,y=b×pgcd(x,y)=p,x=a \times p, y=b \times p,因此,问题被我们转化为了求有多少对(a,b)(a,b),使得a,ba,b满足1a,bNp,gcd(a,b)=11 \leq a,b \leq \frac{N}{p},gcd(a,b)=1

于是子问题的答案为2×(φ(1)+φ(2)+...+φ(Np))12 \times (\varphi(1)+\varphi(2)+...+\varphi(\frac{N}{p}))-1。减一是因为φ(1)\varphi(1)被重复算了两次。

于是,我们就只需要预处理出素数,所有的φ(i)\varphi(i)和其前缀和即可。

φ(i)\varphi (i)表示[1,i][1,i]中有多少个数与ii互质。

\color{blue}{【代码】:}

const int N=1e7+100;
typedef long long ll;
int phi[N];ll prefix_phi[N];
int prime[N],n,tot,t[N];ll ans;
void get_prime_and_phi(int n){
	prefix_phi[0]=0;phi[1]=1;
	for(int i=2;i<=n;i++){
		if (!t[i]){
			phi[i]=i-1;t[i]=i;
			prime[++tot]=i;
		}
		for(int j=1;j<=tot;j++){
			if ((ll)i*prime[j]>(ll)n) break;
			t[i*prime[j]]=prime[j];
			phi[i*prime[j]]=phi[i]*(prime[j]-(prime[j]<t[i]));
			if (prime[j]==t[i]) break;
		}
	}
}
void calc_prefix_phi(int n){
	for(int i=1;i<=n;i++)
		prefix_phi[i]=prefix_phi[i-1]+phi[i];
}
int main(){
	scanf("%d",&n);
	get_prime_and_phi(n);
	calc_prefix_phi(n);
	for(int i=1;i<=tot;i++)
		ans+=2*prefix_phi[n/prime[i]]-1;
	cout<<ans;
	return 0;
}

CF632D   Longest Subsequence\color{green}{CF632D\ \ \ Longest\ Subsequence}

\color{blue}{【题意】:} 给出NN个数(记序列为AA),要求选出尽可能多的数,满足它们的最小公倍数不大于MM。允许数列里没数,此时这个数列的最小公倍数为111n,m1×106,1Ai1×109(1iN)1 \leq n,m \leq 1 \times 10^6,1 \leq A_i \leq 1 \times 10^9(1 \leq i \leq N)

\color{blue}{【思路】:} 首先,很显然的一点是如果某个Ai>M(1iN)A_i>M(1 \leq i \leq N),这个AiA_i是没用的。所以,AA的范围被我们缩小了,有用的AiA_i必然满足1AiM1 \leq A_i \leq M

如果所有的数都是一个数KK的约数,那么它们的最小公倍数(即LCM)必然K\leq K

加上我们发现MM不大,所以我们枚举Q(1QM)Q(1 \leq Q \leq M),表示QQ是所有我们选出的数的约数。问题被我们转化为了求原数列中有多少个数是QQ的约数。

总的时间复杂度为:O(N+M×logM)O(N + M \times \log M)

\color{blue}{【代码】:}
在这里插入图片描述
\color{orange}{主程序:}
在这里插入图片描述
\color{blue}{【关于代码】:}

  • read()函数即快读函数,考虑到大家都会,不再给出。
  • print(a,c)函数即输出一个数aa,同时,在它后面在输出一个字符cc

\color{green}{关于数论}

  • 首先,不得不说,数论很重要。无论是哪门子OI竞赛都很喜欢考。
  • 没有什么快速学懂的好方法,只有多刷多练
  • 别说什么数论只会GCD,数论的题,哪怕是GCDGCD,也有很难的……
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!