Mnnu第三场天梯选拔赛

Mnnu第三场天梯选拔赛

A.

原题链接

点我跳转

题目大意

\(n\)个数,求出所有数对的最小公倍数的最大公约数

解题思路

我们对于某个数\(a_i\),只要看它和区间\([i+1,n]\)的每个数的最小公倍数,因为前面的部分会由前面的数和\(a_i\)去组合,我们不用重复计算。假如要求\(a\)\(b\)\(c\)\(lcm\)\(gcd\)\(gcd(a*b/gcd(a,b),a*c/gcd(a,c))\) ,相当于 \(a*gcd(b/gcd(a,b),c/gcd(a,c))\) , 实际上就是 \(a*gcd(b,c)/gcd(a,b,c)\) ,所以我们可以考虑一手求后缀的gcd,依次转移。

解题代码

#include<bits/stdc++.h>
#define int long long
#define ios std::ios::sync_with_stdio(false)
#define rep(i,a,n) for (int i=a;i<=n;i++)

using namespace std;

const int N = 2e5 + 10, MOD = 1e9+7, inf = 0x3f3f3f3f;
int a[N], g[N];
signed main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];
	g[n] = a[n];
	g[n - 1] = __gcd(a[n], a[n - 1]);
	int res = a[n] / g[n - 1] * a[n - 1];
	for (int i = n - 2; i >= 1; i--){
		g[i] = __gcd(g[i + 1], a[i]);
		res = __gcd(res, a[i] / g[i] * g[i + 1]);
	}
	cout << res << '\n';
    return 0;
}

D.

原题链接

点我跳转

题目大意

解题思路

与该行互质的点会被直接观察到,计算出第\(i\)行的互质数的个数,即求欧拉函数,累计求和。

过题代码

#include<bits/stdc++.h>
#define ios std::ios::sync_with_stdio(false)
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define int long long

using namespace std;

const int N = 2e5 + 10, MOD = 1e9+7, inf = 0x3f3f3f3f;
int vis[N],prime[N],phi[N],len,ans;
signed main()
{
	int n;
	cin >> n;
	if (n == 1) return cout << 0 << '\n',0;
	for (int i = 2; i <= n; i++){
		if (!vis[i]){
			prime[++len] = i;
			phi[i] = i - 1;
		}
		for (int j = 1; j <= len; j++)
		{
			if (prime[j] * i > n) break;
			vis[prime[j] * i] = 1;
			if (i % prime[j] != 0)
				phi[i * prime[j]] = phi[i] * (prime[j] - 1);
			else{
				phi[i * prime[j]] = phi[i] * prime[j];
				break;
			}
		}
	}
	for (int i = 2; i <= n- 1; i++)
		ans += phi[i];
	cout << ans * 2 + 3 << '\n';
    return 0;
}

M.

原题链接

点我跳转

题目大意

给出\(n\)个区间,\(q\)个查询区间,问每次查询时,该查询区间内有多少个点至少被\(k\)个区间覆盖。

解题思路

使用差分数组+前缀和

生成差分数组:a[l]++ , a[r+1]--

前缀和a[i] += a[i-1]

这样处理之后,a[i] 表示 i 这个数符合多少个区间。

sum[i] 逐个记录答案,最后\(O(1)\)查询答案。

解题代码

#include<bits/stdc++.h> 
#define ios std::ios::sync_with_stdio(false)
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define int long long

using namespace std;

const int N = 2e5 + 10, MOD = 1e9+7, inf = 0x3f3f3f3f;
int a[N],sum[N];
signed main()
{
	int m,k,q;
	cin >> m >> k >> q;
	for (int i = 1; i <= m; i++){
		int l,r;
		cin >> l >> r;
		a[l]++, a[r + 1]--;
	}
	for (int i = 1; i < N; i++){
		a[i] += a[i - 1];
		sum[i] = (a[i] >= k? sum[i - 1] + 1 : sum[i - 1]);
	}
	while(q--){
		int l,r;
		cin >> l >> r;
		cout << sum[r] - sum[l - 1] << '\n';
	}
    return 0;
}
posted @ 2020-10-23 19:26  SZyzBO  阅读(101)  评论(0)    收藏  举报