热身赛部分
A Elemental resonance
纯签到模拟题
B
已知gcd和lcm,找到 lcm/gcd的质因数,暴力分配,找最小的和。
(为什么要找质因数?因为如果不是质因数,那么gcd就要变了)
(如何暴力分配?设一共有tot的质因数,分给a和b,可以有2的tot个分配方案)
当然,如果更暴力一点,直接枚举 i 和(lcm/gcd/i),只要两个数互质就可以记录下来找最小
#include<bits/stdc++.h>
using namespace std;
#define int unsigned long long
int num[20],p[20];int tot=0;
signed main()
{
int a,b;cin>>a>>b;int g=__gcd(a,b);int A=1,B=1;int ans=9999999999999999999;
int C=b/a;
for(int i=2;i*i<=C;i++){
if(C%i==0){
num[++tot]=1;p[tot]=i;
while(C%i==0){ num[tot]=p[tot]*num[tot];C=C/i;}
}
}
if(C!=1){num[++tot]=C;p[tot]=C;}
for(int i=0;i<(1<<tot);i++){
A=1;B=1;
for(int j=1;j<=tot;j++){
if((i>>(j-1))&1)A*=num[j];
else B*=num[j];
}
ans=min(ans,(A+B)*g);
}
cout<<ans;
return 0;
}
C Oldier array
纯暴力题/背包
思路:
首先如果是1,那么所有自然数都能取到,所以输出-1;
如果b数组的数都不是互质的,那么趋向无限的时候总会有数字取不到的;
(例如4,6,14,公因数是2,那么无限大的时候偶数都是去不到的)
剩下的部分因为n<100,a[i]<100,所以直接暴力背包就可以了
#include<bits/stdc++.h>
using namespace std;
int a[104];bool dp[10005];
int main()
{
int n;cin>>n;bool flag;
for(int i=0;i<n;i++){cin>>a[i];if(a[i]==1){cout<<-1;return 0;}}
int res=a[0];dp[0]=1;
for(int i=1;i<n;i++)res=__gcd(res,a[i]);
if(res!=1){cout<<-2;return 0;}
for(int j=1;j<=10005;j++)
for(int i=0;i<n;i++)
if(j-a[i]>=0&&dp[j-a[i]]==1)dp[j]=1;
for(int i=10000;i>=1;i--){
if(dp[i]==0){cout<<i<<" ";return 0;}
}
return 0;
}
N Nine Is Greater Than
纯模拟
#include<bits/stdc++.h>
using namespace std;
int main()
{
string a,b;cin>>a>>b;
if(a>b)cout<<a<<'>'<<b;if(a==b)cout<<a<<'='<<b;if(a<b)cout<<a<<'<'<<b;
}
G Gua!
纯模拟
#include<bits/stdc++.h>
using namespace std;
int main()
{
int T;cin>>T;int b,r,d,s;
while(T--){
cin>>b>>r>>d>>s;
if(r==0&&d>0)cout<<"gua!\n";
else if(((r+60)/60)*b<d)cout<<"gua!\n";
else cout<<"ok\n";
}
return 0;
}
A Another A+B Problem
简单的暴力
但是我的代码写的太难看了,就像危楼的建筑orz所以学了一下别人的写法
(模拟好难qwq)
#include<bits/stdc++.h>
using namespace std;
vector< string >v;string s,f;bool B[10];int P[10];
string tos(int x){
string s="";s.push_back(x/10+'0');s.push_back(x%10+'0');return s;
}
bool check(int x,int y,int z)
{
int coun[10]={0};
string now=tos(x)+"+"+tos(y)+"="+tos(z);
for(int i=0;i<now.size();i++)coun[now[i]-'0']++;
for(int i=0;i<now.size();i++){
if(f[i]=='G'){if(now[i]!=s[i])return 0;}
else if(f[i]=='P'){if(now[i]==s[i])return 0;}
else if(f[i]=='B'){if(now[i]==s[i])return 0;}
}
for(int i=0;i<10;i++){
if(B[i]){
if(P[i]&&P[i]!=coun[i])return 0;
if(!P[i]&&coun[i])return 0;
}
else if(P[i]>coun[i])return 0;
}
return 1;
}
int main()
{
cin>>s>>f;
for(int i=0;i<f.size();i++){
if(f[i]=='B')B[s[i]-'0']=1;
else P[s[i]-'0']++;
}
for(int i=0;i<100;i++)
for(int j=0;j<100;j++){
int k=i+j;
if(k<100&&check(i,j,k))
v.push_back(tos(i)+"+"+tos(j)+"="+tos(k));
}
cout<<v.size()<<'\n';
for(int i=0;i<v.size();i++) cout<<v[i]<<'\n';
return 0;
}
M题
用tarjan算强连通分量,之后按照拓扑的顺序把在底下的大学相加就可以了
#include<bits/stdc++.h>
using namespace std;
int dfn[1000006],low[1000006];
vector<int>v[1000006];
vector<int>color[1000006];
int a[1000006],timz=0,id=0;
stack<int>st;
bool vis[1000006];
int ans[1000006]={0};
void tarjan(int u){
dfn[u]=low[u]=++timz;
st.push(u);
vis[u]=1;
for(int i=0;i<v[u].size();i++){
int y=v[u][i];
if(dfn[y]==0){
tarjan(y);
low[u]=min(low[u],low[y]);
}
else if(vis[y]){
low[u]=min(low[u],low[y]);
}
}
if(dfn[u]==low[u]){
id++;
while(true){
int vv=st.top();
color[id].push_back(vv);
vis[vv]=0;
st.pop();
if(vv==u)break;
}
}
}
int main()
{
int n,m;cin>>n>>m;
for(int i=0;i<m;i++){
for(int j=1;j<=n;j++){cin>>a[j];}
for(int j=2;j<=n;j++){
v[a[j-1]].push_back(a[j]);
}
}
tarjan(a[1]);
int res=0;
for(int i=1;i<=id;i++){
res+=color[i].size();
for(auto q:color[i]){
ans[q]=res-1;
}
}
for(int i=1;i<=n;i++)cout<<ans[i]<<' ';
}