当时过了点了就没打,现在补上
A. 简单的整除
题面
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int d[4]={2,3,5,7};
int main() {
::sync_with_stdio(false);
iosint x;
>>x;
cinbool flag=false;
for(int i=0;i<4;i++)
{
if(x%d[i]==0)
{
=true;
flagbreak;
}
}
if(flag)
<<"YES"<<'\n';
coutelse
<<"NO"<<'\n';
coutreturn 0;
}
B. 整数划分
题面
肯定是按照1,2,3,...
这样下去是最优的,只用关注最后一个的取值就行
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
<int>s;
vectorint main() {
::sync_with_stdio(false);
iosint T;
>>T;
cinwhile(T--)
{
.clear();
sint n;
>>n;
cinint i=1;
for(i=1;i<=n;i++)
{
.push_back(i);
s-=i;
n}
if(i>n)
.push_back(n);
sint l=s.size();
if(s[l-1]<=s[l-2])
{
[l-2]+=s[l-1];
s.pop_back();
s}
for(int i=0;i<s.size()-1;i++)
<<s[i]<<' ';
cout<<s[s.size()-1]<<'\n';
cout}
return 0;
}
C. 传送阵
题面
显然就是统计不同值的格子数
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
<int,bool>mp;
mapint main() {
::sync_with_stdio(false);
iosint T;
>>T;
cinwhile(T--)
{
.clear();
mpint n,m;
>>n>>m;
cinfor(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
int x;
>>x;
cin[x]=true;
mp}
}
<<mp.size()<<'\n';
cout}
return 0;
}
D. 修改后的和
题面
每一次操作之后对总和的贡献为
如果选择要对
综上,只用找出来
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
[N];
ll aint main() {
::sync_with_stdio(false);
iosint T;
>>T;
cinwhile(T--)
{
int n,m;
>>n>>m;
cin=0;
ll sum<ll>s;
vectorfor(int i=1;i<=n;i++)
{
>>a[i];
cinif(a[i]>0)
.push_back(a[i]*(n-i+1));
s+=a[i];
sum}
if(s.size()==0)
{
<<sum<<'\n';
coutcontinue;
}
(s.begin(),s.end());
sort(s.begin(),s.end());
reversefor(int i=0;i<min(m,(int)s.size());i++)
-=s[i];
sum<<sum<<'\n';
cout}
return 0;
}
E. 幼稚园的树2
题面
可以发现每棵树的生长是有循环的,计算一下就行
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int h[N],a[N];
int main() {
::sync_with_stdio(false);
iosint T;
>>T;
cinwhile(T--)
{
int n,m,k,b;
>>n>>m>>k>>b;
cinfor(int i=1;i<=n;i++)
>>h[i];
cinfor(int i=1;i<=n;i++)
>>a[i];
cinif(m==1)
{
for(int i=1;i<=n;i++)
<<h[i]<<' ';
cout<<'\n';
coutcontinue;
}
for(int i=1;i<=n;i++)
{
int st=(k-h[i])/a[i]+1;
int s=(k-b)/a[i]+1;
if(st>m-1)
<<h[i]+(m-1)*a[i]<<' ';
coutelse
<<b+(m-1-st)%s*a[i]<<' ';
cout}
<<'\n';
cout}
return 0;
}
F. 最便宜的构建
题面
查询是否连通,可以使用并查集
正着思考不太容易,可以考虑枚举验证,发现枚举验证挺容易,但是复杂度很大。用二分优化
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,k;
const int N=1e5+5;
struct arc
{
int a,b,w;
}a[N];
int f[N];
<int>q[N];
vectorbool cmp(arc x,arc y){return x.w<y.w;}
int find(int x)
{
return x==f[x]?x:f[x]=find(f[x]);
}
void merge(int x,int y)
{
=find(x);y=find(y);
xif(x!=y)
[x]=y;
f}
bool judge(int x)
{
for(int i=1;i<=n;i++)
[i]=i;
ffor(int i=1;i<=x;i++)
(a[i].a,a[i].b);
mergefor(int i=1;i<=k;i++)
{
int now=find(q[i][0]);
for(auto x:q[i])
if(find(x)!=now)
return false;
}
return true;
}
int main() {
::sync_with_stdio(false);
ios>>n>>m;
cinfor(int i=1;i<=m;i++)
>>a[i].a>>a[i].b>>a[i].w;
cin>>k;
cinfor(int i=1;i<=k;i++)
{
int x;
>>x;
cinfor(int j=1;j<=x;j++)
{
int y;
>>y;
cin[i].push_back(y);
q}
}
(a+1,a+1+m,cmp);
sortint l=1,r=m,ans=m;
while(l<r)
{
int mid=(l+r)>>1;
if(judge(mid))
{
=mid;
ans=mid;
r}
else
=mid+1;
l}
<<a[ans].w<<'\n';
coutreturn 0;
}
并查集一定要加查找优化,不加会炸,一下午的debug的教训🤡