练习记录-atcoder-abc292(A-E)

E是补的 考试的时候写的垃圾dfs 有地方错了 没过

A 小写转换大写

#include<bits/stdc++.h>
#define close     std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN = 3e5+7;
const ll mod =1e9+7;
const ll inf =0x3f3f3f3f;
const ll INF =0x3f3f3f3f3f3f3f3f;

int gcd(int x,int y){int k=0; if(x<y){k=x;x=y;y=k;}while(x%y!=0){k=x%y;x=y;y=k;}return y;}
ll _power(ll a,int b){ll ans=1,res=a;while(b){if(b&1) ans=ans*res%mod;res=res*res%mod;b>>=1;}return ans%mod;}
void solve(){
        string s;
        cin>>s;
        for(int i=0;i<s.length();i++){
            if(s[i]<='z'&&s[i]>='a'){
                char ch=s[i]-32;
                cout<<ch; 
            }
            else
            cout<<s[i]; 
        }
}
int main(){
    solve();
}
View Code

B 计算黄牌红牌个数 输出是否罚下场 拿个数组记录就行 黄牌++,红牌直接+2,大于2就下场

#include<bits/stdc++.h>
#define close     std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN = 3e5+7;
const ll mod =1e9+7;
const ll inf =0x3f3f3f3f;
const ll INF =0x3f3f3f3f3f3f3f3f;
int f[MAXN];
int gcd(int x,int y){int k=0; if(x<y){k=x;x=y;y=k;}while(x%y!=0){k=x%y;x=y;y=k;}return y;}
ll _power(ll a,int b){ll ans=1,res=a;while(b){if(b&1) ans=ans*res%mod;res=res*res%mod;b>>=1;}return ans%mod;}
void solve(){
    int n,m;cin>>n>>m;
    for(int i=0;i<m;i++){
        int o,p;cin>>o>>p;
        if(o==3){
            if(f[p]>=2) cout<<"Yes\n";
            else cout<<"No\n"; 
        }
        else if(o==2){
            f[p]=2;
        }
        else f[p]++;
    }
}
int main(){
    solve();
}
View Code

C 寻找正整数ABCD的可能组合数量 使AB+CD=N

想了很久 决定暴力,先预处理出对于一个数(1-200000) 乘法分解的可能数量

(如果分解到乘方方法数就+1,否则方法数+2)

最后遍历(1-n) 对每两组数的方法数相乘求和即可

#include<bits/stdc++.h>
#define close     std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN = 3e5+7;
const ll mod =1e9+7;
const ll inf =0x3f3f3f3f;
const ll INF =0x3f3f3f3f3f3f3f3f;
ll f[MAXN];
int gcd(int x,int y){int k=0; if(x<y){k=x;x=y;y=k;}while(x%y!=0){k=x%y;x=y;y=k;}return y;}
ll _power(ll a,int b){ll ans=1,res=a;while(b){if(b&1) ans=ans*res%mod;res=res*res%mod;b>>=1;}return ans%mod;}
void solve(){
    int n;cin>>n;
    for(int i=1;i<=200000;i++){
        for(int j=1;j<=sqrt(i);j++){
            if(i%j==0){
                f[i]++;
                if(j*j!=i) f[i]++;
            }
        } 
    }
    ll ans=0;
    for(int i=1;i<n;i++){
        ans+=f[i]*f[n-i];
    } 
    cout<<ans;
}
int main(){
  close;
    solve();
}
View Code

D 题意求对每个连通区块,是否满足点数==变数

使用并查集处理一遍

1遍历每一个边,记录每个区块的边数

2遍历每个点 记录每个区块的点数

3遍历每个点 检查边数点数是否相等

#include<bits/stdc++.h>
#define close     std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN = 3e5+7;
const ll mod =1e9+7;
const ll inf =0x3f3f3f3f;
const ll INF =0x3f3f3f3f3f3f3f3f;
int f[MAXN],n,m,sum[MAXN],k[MAXN];
struct node{
    int u,v;
}N[MAXN];
void clean(){
    for(int i=1;i<=n;i++) f[i]=i;
}
int find(int x){
    if(x!=f[x]) f[x]=find(f[x]);  return f[x];
} 
void add(int x,int y){
    int fx=find(x),fy=find(y); 
    if(fx!=fy) f[fx]=fy;
}
void solve(){
    cin>>n>>m;
    clean();
    for(int i=1;i<=m;i++){
        cin>>N[i].u>>N[i].v;
        add(N[i].u,N[i].v);
    }
    for(int i=1;i<=m;i++){
        f[N[i].u]=find(N[i].u);
        sum[f[N[i].u]]++;    
    }
    //int maxs=0,maxt=0;
    int flag=1;
    for(int i=1;i<=n;i++){
        k[f[i]]++;
        //if(f[i]!=sz[i].size()) flag=0;
    }
    for(int i=1;i<=n;i++){
    //    k[f[i]]++;
        if(sum[i]!=k[i]) flag=0;
    }
    if(flag) cout<<"Yes\n";
    else cout<<"No\n";
}
int main(){
    solve();
}
View Code

E 寻找对于每个点能到达的长度>=2的点的个数

原来使用n^2遍历+dfs检查长度 很复杂 如果有大佬debug感谢orz

#include<bits/stdc++.h>
#define close     std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN = 3e5+7;
const ll mod =1e9+7;
const ll inf =0x3f3f3f3f;
const ll INF =0x3f3f3f3f3f3f3f3f;
#define int long long
int f[2005];
vector<int> adj[2005];
int dfs(int u,int v,int val){
    int flag=0;
    for(auto it:adj[u]){
        if(f[it]) continue;
        if(it==v&&val) return 1;
        else {
            f[it]=1;
            flag=max(flag,dfs(it,v,1));
            f[it]=0;
        }
    }
    return flag;
}
void solve(){
    int n,m;cin>>n>>m;
    for(int i=0;i<m;i++){
        int u,v;
        cin>>u>>v;
        adj[u].push_back(v);
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(j==i) continue;
            f[i]=1;
            if(dfs(i,j,0)) ans++;
            f[i]=0;
        }
    }
    cout<<ans;
}
signed main(){
    solve();
}
View Code

看了官方题解,直接记录所有的点能到达的点的数量,最后减去边的数量(其实就是长度为1的对数) 就是正确答案 用bfs来寻找连通数量

#include<bits/stdc++.h>
#define close     std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN = 3e5+7;
const ll mod =1e9+7;
const ll inf =0x3f3f3f3f;
const ll INF =0x3f3f3f3f3f3f3f3f;
vector<int> adj[2005];
int f[2005];
int gcd(int x,int y){int k=0; if(x<y){k=x;x=y;y=k;}while(x%y!=0){k=x%y;x=y;y=k;}return y;}
ll _power(ll a,int b){ll ans=1,res=a;while(b){if(b&1) ans=ans*res%mod;res=res*res%mod;b>>=1;}return ans%mod;}
void solve(){
    int n,m;
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int u,v;
        cin>>u>>v;
        adj[u].push_back(v);
    } 
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++) f[j]=0;
        f[i]=1;
        queue<int> sz;
        sz.push(i);
        while(sz.size()){
            int x=sz.front();
            sz.pop();
            for(auto it:adj[x]){
                if(f[it]) continue;
                sz.push(it);
                ans++;
                f[it]=1;
            }    
        }
    }
    ans-=m;
    cout<<ans; 
}
int main(){
    solve();
}
View Code

 

F好像是数学题 后续有补将继续更新

posted @ 2023-03-05 11:00  xishuiw  阅读(29)  评论(0编辑  收藏  举报