当时过了点了就没打,现在补上
A. 简单的整除
题面
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int d[4]={2,3,5,7};
int main() {
ios::sync_with_stdio(false);
int x;
cin>>x;
bool flag=false;
for(int i=0;i<4;i++)
{
if(x%d[i]==0)
{
flag=true;
break;
}
}
if(flag)
cout<<"YES"<<'\n';
else
cout<<"NO"<<'\n';
return 0;
}B. 整数划分
题面
肯定是按照1,2,3,...这样下去是最优的,只用关注最后一个的取值就行
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<int>s;
int main() {
ios::sync_with_stdio(false);
int T;
cin>>T;
while(T--)
{
s.clear();
int n;
cin>>n;
int i=1;
for(i=1;i<=n;i++)
{
s.push_back(i);
n-=i;
}
if(i>n)
s.push_back(n);
int l=s.size();
if(s[l-1]<=s[l-2])
{
s[l-2]+=s[l-1];
s.pop_back();
}
for(int i=0;i<s.size()-1;i++)
cout<<s[i]<<' ';
cout<<s[s.size()-1]<<'\n';
}
return 0;
}C. 传送阵
题面
显然就是统计不同值的格子数
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
map<int,bool>mp;
int main() {
ios::sync_with_stdio(false);
int T;
cin>>T;
while(T--)
{
mp.clear();
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
int x;
cin>>x;
mp[x]=true;
}
}
cout<<mp.size()<<'\n';
}
return 0;
}D. 修改后的和
题面
每一次操作之后对总和的贡献为
如果选择要对
综上,只用找出来
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
ll a[N];
int main() {
ios::sync_with_stdio(false);
int T;
cin>>T;
while(T--)
{
int n,m;
cin>>n>>m;
ll sum=0;
vector<ll>s;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]>0)
s.push_back(a[i]*(n-i+1));
sum+=a[i];
}
if(s.size()==0)
{
cout<<sum<<'\n';
continue;
}
sort(s.begin(),s.end());
reverse(s.begin(),s.end());
for(int i=0;i<min(m,(int)s.size());i++)
sum-=s[i];
cout<<sum<<'\n';
}
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() {
ios::sync_with_stdio(false);
int T;
cin>>T;
while(T--)
{
int n,m,k,b;
cin>>n>>m>>k>>b;
for(int i=1;i<=n;i++)
cin>>h[i];
for(int i=1;i<=n;i++)
cin>>a[i];
if(m==1)
{
for(int i=1;i<=n;i++)
cout<<h[i]<<' ';
cout<<'\n';
continue;
}
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)
cout<<h[i]+(m-1)*a[i]<<' ';
else
cout<<b+(m-1-st)%s*a[i]<<' ';
}
cout<<'\n';
}
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];
vector<int>q[N];
bool 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)
{
x=find(x);y=find(y);
if(x!=y)
f[x]=y;
}
bool judge(int x)
{
for(int i=1;i<=n;i++)
f[i]=i;
for(int i=1;i<=x;i++)
merge(a[i].a,a[i].b);
for(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() {
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=m;i++)
cin>>a[i].a>>a[i].b>>a[i].w;
cin>>k;
for(int i=1;i<=k;i++)
{
int x;
cin>>x;
for(int j=1;j<=x;j++)
{
int y;
cin>>y;
q[i].push_back(y);
}
}
sort(a+1,a+1+m,cmp);
int l=1,r=m,ans=m;
while(l<r)
{
int mid=(l+r)>>1;
if(judge(mid))
{
ans=mid;
r=mid;
}
else
l=mid+1;
}
cout<<a[ans].w<<'\n';
return 0;
}并查集一定要加查找优化,不加会炸,一下午的debug的教训🤡