SMU Summer 2024 Contest Round 3
知识点模块
1.判断一个数是否为3的倍数,只需要把每一位上的数加起来看总和,总和取余3为0就是3的倍数,这个性质可以用来做判断删除数位的题
题解模块
寻找素数对
1.先用埃筛法把10000以内的素数放到一个数组里面,然后循环寻找一下,符合和的情况,更新差值最小的就行
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
#define all(v) v.begin(),v.end()
int dx[]={0,1,-1,0};
int dy[]={-1,0,0,1};
bool isp[100010];
int a[100010];
void isf()
{
for(int i=0;i<10005;i++) isp[i]=1;
isp[0]=isp[1]=0;
for(int i=2;i<10005;i++)
{
if(isp[i])
{
for(int j=2*i;j<=10005;j+=i)
{
isp[j]=0;
}
}
}
}
void solve()
{
vector<int>ve;
for(int i=0;i<10005;i++)
{
if(isp[i]==1) ve.push_back(i);
}
// cout<<ve.size()
int n;
while(cin>>n){
int ans1,ans2;
int minn=1e9;
for(int i=0;i<ve.size();i++)//还可以优化为一层循环,左右指针即可
{
for(int j=ve.size()-1;j>=i;j--)
{
if(ve[i]+ve[j]==n){
minn=min(ve[j]-ve[i],minn);
if(minn==ve[j]-ve[i]){
ans1=ve[i],ans2=ve[j];
}
}
}
}
cout<<ans1<<" "<<ans2<<endl;
}
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0);
isf();
int t=1;
//cin>>t;
while(t--) solve();
return 0;
}
抱歉
1.n个点n条曲线把平面分成两份,每加1条边,平面就被多分割一份
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
#define all(v) v.begin(),v.end()
int dx[]={0,1,-1,0};
int dy[]={-1,0,0,1};
void solve()
{
int n,m;
while(cin>>n>>m&&n!=0)
{
cout<<n+m-2;
cout<<endl;
}
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0);
int t=1;
//cin>>t;
while(t--) solve();
return 0;
}
Nuts
签到题
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
#define all(v) v.begin(),v.end()
int dx[]={0,1,-1,0};
int dy[]={-1,0,0,1};
void solve()
{
int n,sum=0;
cin>>n;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
if(x<=10) continue;
else {
sum+=x-10;
}
}
cout<<sum;
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0);
int t=1;
//cin>>t;
while(t--) solve();
return 0;
}
To 3
1.首先根据知识点1,我们可以先算出每个数位的和,并且开数组统计每个数位取余3的数的数量,显然只有余数1和2
2.如果数位总和取余3为1的话,我们看cnt【1】是否>=1并且数位总数是不是大于1,如果是就删掉这个等价1,如果取余3为2的话同理
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
#define all(v) v.begin(),v.end()
int dx[]={0,1,-1,0};
int dy[]={-1,0,0,1};
void solve()
{
int n;
cin>>n;
if(n%3==0)
{
cout<<0;
return;
}
if(n<=10){
if(n%3!=0){
cout<<-1;
return ;
}
}
int sum=0;//所有数位的数加起来总和
int tt=0;//总共有几位数
int cnt[5]={0};
while(n)
{
int p=n%10;//每个数位上的数
cnt[p%3]++;
sum+=n%10;
n/=10;
tt++;
}
//等价1就是与3取余为1的数1 4 7
//等价2就是2 5 8
if(sum%3==1)
{
//删除数一定要考虑数位是否是足够的
if(cnt[1]>=1&&tt>1) cout<<1; //当总和取余3为1,只需要删掉一个等价1的数即可
else if(cnt[2]>=2&&tt>2) cout<<2;//没有一个等价1 就删俩个等价2
else cout<<-1;
}else if(sum%3==2)//同理
{
if(cnt[2]>=1&&tt>1) cout<<1;
else if(cnt[1]>=2&&tt>2) cout<<2;
else cout<<-1;
}
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0);
int t=1;
//cin>>t;
while(t--) solve();
return 0;
}
Bowls and Dishes
1.这题不确定k次中,我们要选第一个数还是第二个数,那么使用二进制枚举,列举所有情况找最大值是合适的解法
2.二进制枚举中的每个数位的01就是代表我们k次中,每次选择第一个数或者第二个数,for循环中的i就代表着每一种情况
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
#define all(v) v.begin(),v.end()
int dx[]={0,1,-1,0};
int dy[]={-1,0,0,1};
void solve()
{
int n,m;
cin>>n>>m;
pii p[105],pe[105];
for(int i=1;i<=m;i++)
{
cin>>p[i].x>>p[i].y;
}
int k;cin>>k;
for(int i=0;i<k;i++)
{
cin>>pe[i].x>>pe[i].y;
}
map<int,int>fi;
int maxx=0;
for(int i=0;i<(1<<k);i++)//i代表的是选择情况,比如当k=3时,1是001,
//001 每个数位上代表着对每个人选择第一个数或第二个数,0代表选第一个,1代表选第二个
{
fi.clear();//每次重新进去循环记得把之前的标记清空
int ans=0;
for(int j=0;j<k;j++)
{
if((i>>j)&1) fi[pe[j].x]=1;//i>>j想象成把一位数往右挪去判断数位上是0还是1
else fi[pe[j].y]=1;
}
for(int i=1;i<=m;i++){
int xx=p[i].x,yy=p[i].y;
if(fi[xx]==1&&fi[yy]==1) ans++;
}
maxx=max(ans,maxx);
}
cout<<maxx;
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0);
int t=1;
//cin>>t;
while(t--) solve();
return 0;
}
posted on 2024-07-10 14:54 swj2529411658 阅读(34) 评论(0) 收藏 举报
浙公网安备 33010602011771号