Codeforces Round #837 A~C题解
补题链接
前排提示:一些个人废话,想看题解直接往下看。
因为要打杭州打星,昨天才终于到家,十一点到,吃了口饭,赶紧上号cf,想着上一波分,但是结果不尽人意。A题第一发WA了,想到需要特判数组数值相同的情况,结果把组合数
A
n
2
A_{n}^2
An2直接当成了
n
!
n!
n!。WA了好几发才发现。B题,思维题,第一遍忘记考虑了后续点对前面点的影响,想到之后,没想好怎么样去更新。直接用*min_element()超时了,时间来不及,最后遗憾掉分。
A Hossam and Combinatorics 思维
题意:给你一组数,求出满足两数差的绝对值等于该数组的极差的对数。
思路:直接统计最小值和最大值数量,然后相乘再乘2即可。注意!特判最大值和最小值相同的情况。这时候数组中所有元素值相同,所以对数的结果就是
A
n
2
=
n
∗
(
n
−
1
)
A_{n}^2=n*(n-1)
An2=n∗(n−1)。注意开long long。
代码:
void solve(){
LL n;
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
LL minn=*min_element(a,a+n);//求出最小值
LL maxn=*max_element(a,a+n);//求出最大值
LL n1=count(a,a+n,minn);//统计最小值数量
LL n2=count(a,a+n,maxn);//统计最大值数量
//特判 数组中元素全部相同的情况
if(minn==maxn) cout<<LL(n*(n-1))<<endl;
else cout<<LL(n1*n2*2)<<endl;
return;
}
B. Hossam and Friends 思维
题意:给你一个数n,表示有1~n个数。 给你m个限制,每个限制给出a和b,说明a和b不能同时出现。求出满足[
a
i
,
a
j
a_{i},a_{j}
ai,aj]的数量。
思路:对于每组限制的输入,我们用一个数组来存,如果一个结点存在多组情况,比如1 2和1 3。根据题意,1 2的情况包含了1 3的情况。所以多组情况,我们维护最小值即可。对于每组限制b[i],对答案的贡献为b[i]-i。这里还需注意!后续的情况是会对前面的情况有影响的。比如1的限制最小的情况是4, 2的最小限制3,那么本来1的情况可以取[1],[1,2],[1,2,3]。但由于2的限制是3。所以1的情况只能[1],[1,2]。等价于1的限制缩小到了2的限制,也就是3。这样我们就需要维护一个后缀最小值。
代码:
void solve(){
LL n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) b[i]=n+1;//初始化
while(m--){
int x,y;
cin>>x>>y;
if(x>y) swap(x,y);//限制统一小的在前
b[x]=min(b[x],y);
}
for(int i=n-1;i>0;i--){//维护后缀最小值
b[i]=min(b[i],b[i+1]);
}
LL ans=n*(n+1)/2;
for(int i=1;i<n;i++){
ans-=(n-b[i]+1);
}
cout<<ans<<endl;
return;
}
C. Hossam and Trainees 数学+质因数分解
题意:给你n个数,判断n个数中是否有两个数的最大公约数大于1.
思路;我们对每个数进行质因数分解,如果n个数中存在了相同的质因数,那么说明满足情况。因为数据范围是1e9,质因数分解的复杂度是O(
n
\sqrt{n}
n)。所以我们可以提前预处理所有的素数。有一个结论,前n个数中有
n
ln
n
\frac{n}{\ln{n}}
lnnn。所以本题的质数不超过40000个,可以通过。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=2e5+10;
int a[N];
vector<int> prime;
bool st[N];
void get_primes(int n){//筛素数
for(int i=2;i<=n;i++){
if(!st[i]) prime.pb(i);
for(int j=0;prime[j]<=n/i;j++){
st[prime[j]*i]=true;
if(i%prime[j]==0) break;
}
}
}
void solve(){
int n;
cin>>n;
map<int,int> mp;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++){
int num=a[i];
for(int p:prime){
if(p*p>num) break;
if(num%p==0){
while(num%p==0) num/=p;
mp[p]++;
if(mp[p]>=2){
cout<<"YES"<<endl;
return;
}
}
}
if(num>1) mp[num]++;
if(mp[num]>=2){
cout<<"YES"<<endl;
return;
}
}
cout<<"NO"<<endl;
return;
}
int main()
{
get_primes(40000);
int T;
cin>>T;
while(T--){
solve();
}
return 0;
}