22.9.24 比赛

热身赛部分

热身赛

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]<<' ';
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值