CF1780F Three Chairs

CF1780F Three Chairs

题目大意

有一个长度为 n n n的正整数序列 a i a_i ai,序列中的元素两两不同。你可以从序列中任取不同的三个元素组成一个三元组,当三元组中最大的数和最小的数两者互质,则这个三元组为合法的三元组,求这个序列中的元素组成的三元组中有多少个三元组为合法的三元组?


题解

首先我们可以将 a a a数组排序。

f i f_i fi表示第 i i i个元素和在第 i i i个元素之前的元素作为最大值和最小值的合法三元组的个数,则有

f i = ∑ j = 1 i ( i − j − 1 ) × [ gcd ⁡ ( a i , a j ) = = 1 ] f_i=\sum\limits_{j=1}^i(i-j-1)\times [\gcd(a_i,a_j)==1] fi=j=1i(ij1)×[gcd(ai,aj)==1]

那么答案即为

∑ i = 1 n f i = ∑ i = 1 n ∑ j = 1 i ( i − j − 1 ) × [ gcd ⁡ ( a i , a j ) = = 1 ] \sum\limits_{i=1}^n f_i=\sum\limits_{i=1}^n\sum\limits_{j=1}^i(i-j-1)\times [\gcd(a_i,a_j)==1] i=1nfi=i=1nj=1i(ij1)×[gcd(ai,aj)==1]

根据莫比乌斯函数的性质,原式变为

∑ i = 1 n ∑ j = 1 i ( i − j − 1 ) × ∑ k ∣ a i , k ∣ a j μ ( k ) \sum\limits_{i=1}^n\sum\limits_{j=1}^i(i-j-1)\times\sum\limits_{k|a_i,k|a_j}\mu(k) i=1nj=1i(ij1)×kai,kajμ(k)

先枚举 k k k

∑ k = 1 a n μ ( k ) ∑ k ∣ a i ∑ k ∣ a j , j < i ( i − j − 1 ) \sum\limits_{k=1}^{a_n}\mu(k)\sum\limits_{k|a_i}\sum\limits_{k|a_j,j<i}(i-j-1) k=1anμ(k)kaikaj,j<i(ij1)

用桶来存 a a a数组,枚举 k k k,然后枚举 k k k的倍数,后面的式子就可以由前缀和求出。

m x mx mx表示 a a a的最大值,总共枚举的次数为 m x + m x 2 + m x 3 + ⋯ + m x m x ≈ m x ln ⁡ m x mx+\dfrac{mx}{2}+\dfrac{mx}{3}+\cdots+\dfrac{mx}{mx}\approx mx\ln mx mx+2mx+3mx++mxmxmxlnmx,所以时间复杂度为 O ( m x ln ⁡ m x ) O(mx\ln mx) O(mxlnmx)

code

#include<bits/stdc++.h>
using namespace std;
const int N=300000;
int n,a[300005],v[300005],z[300005],p[300005],mu[300005];
long long sum,tmp,w,ans=0;
void init(){
	mu[1]=1;
	for(int i=2;i<=N;i++){
		if(!z[i]){
			p[++p[0]]=i;
			mu[i]=-1;
		}
		for(int j=1;j<=p[0]&&i*p[j]<=N;j++){
			z[i*p[j]]=1;
			if(i%p[j]==0) break;
			mu[i*p[j]]=-mu[i];
		}
	}
}
int main()
{
	init();
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++){
		v[a[i]]=i;
	}
	for(int i=1;i<=a[n];i++){
		sum=tmp=w=0;
		for(int j=i;j<=a[n];j+=i){
			if(!v[j]) continue;
			sum+=(v[j]-1)*w-tmp;
			++w;tmp+=v[j];
		}
		ans+=mu[i]*sum;
	}
	printf("%lld",ans);
	return 0;
}
The Sleeping Teaching Assistant A university computer science department has a teaching assistant (TA) who helps undergraduate students with their programming assignments during regular office hours. The TA&rsquo;s office is rather small and has room for only one desk with a chair and computer. There are three chairs in the hallway outside the office where students can sit and wait if the TA is currently helping another student. When there are no students who need help during office hours, the TA sits at the desk and takes a nap. If a student arrives during office hours and finds the TA sleeping, the student must awaken the TA to ask for help. If a student arrives and finds the TA currently helping another student, the student sits on one of the chairs in the hallway and waits. If no chairs are available, the student will come back at a later time. Using POSIX threads, mutex locks, and/or semaphores, implement a solution that coordinates the activities of the TA and the students. Details for this assignment are provided below. Using Pthreads, begin by creating N students. Each will run as a separate thread. The TA will run as a separate thread as well. Student threads will alternate between programming for a period of time and seeking help from the TA. If the TA is available, they will obtain help. Otherwise, they will either sit in a chair in the hallway or, if no chairs are available, will resume programming and will seek help at a later time. If a student arrives and notices that the TA is sleeping, the student must notify the TA using a semaphore. When the TA finishes helping a student, the TA must check to see if there are students waiting for help in the hallway. If so, the TA must help each of these students in turn. If no students are present, the TA may return to napping. Perhaps the best option for simulating students programming—as well as the TA providing help to a student—is to have the appropriate threads sleep for a random period of time using the sleep() API:
06-04
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值