Mnnu第三场天梯选拔赛
作者:互联网
Mnnu第三场天梯选拔赛
A.
原题链接
题目大意
给$n$个数,求出所有数对的最小公倍数的最大公约数
解题思路
我们对于某个数$a_i$,只要看它和区间$[i+1,n]$的每个数的最小公倍数,因为前面的部分会由前面的数和$a_i$去组合,我们不用重复计算。假如要求$a$对$b$、$c$的$lcm$ 的$gcd$ ,$gcd(ab/gcd(a,b),ac/gcd(a,c))$ ,相当于$agcd(b/gcd(a,b),c/gcd(a,c))$, 实际上就是$agcd(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;
}
标签:prime,long,gcd,int,Mnnu,--,选拔赛,第三场,define 来源: https://www.cnblogs.com/zhengyongjin/p/13865787.html