zoukankan      html  css  js  c++  java
  • 牛客小白月赛23

    牛客小白月赛23 

    A. 膜法记录

    和我签订契约成为魔法少女吧!

    题意:n行m列网格中分布着敌人,可以进行a次行blast和b次列blast,问能否全歼敌人 。(T≤105,n≤5,m≤105或T=1,n≤20,m≤105

    思路:n比较小,枚举每行是否选取即可。

    #include <bits/stdc++.h>
    using namespace std;
    const int M=1e5+100;
    int n,m,a,b;
    char Mp[10][M];
    bool Biu[10],All_dead;
    bool OK(){
        set<int> col;
        for(int i=1;i<=n;i++){
            if(Biu[i]) continue;
            for(int j=1;j<=m;j++)
                if(Mp[i][j]=='*') col.insert(j);
        }
        return b>=col.size();
    }
    void DFS(int Row,int Biu_num){
        if(Row>n+1||Biu_num>a) return;
        if(OK()){All_dead=true;return;}
        Biu[Row]=true;
        DFS(Row+1,Biu_num+1);
        Biu[Row]=false;
        DFS(Row+1,Biu_num);
    }
    void solve(){
        All_dead=false;
        fill(Biu,Biu+10,false);
        cin>>n>>m>>a>>b;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                cin>>Mp[i][j];
        DFS(1,0);
        cout<<(All_dead?"yes":"no")<<"
    ";
    }
    int main()
    {
        int t;cin>>t;
        while(t--)
            solve();
        return 0;
    }
    View Code

    B. 阶乘

    题意:共T次询问,每次询问给定一个正整数p,求阶乘是p的倍数的最小正整数n。(T≤103,p≤109

    思路:分解质因数,存储每个质因数的个数,将重复的质因数分配到其倍数中。

    Tips:p可能为109规模的质数,散列数组一方面内存利用率较低,一方面开不到这个大小,所以使用map存储。取质因数取到根号n即可,注意最后将p也存起来。

    #include <bits/stdc++.h>
    using namespace std;
    void solve(){
        int p;cin>>p;
        map<int,int> _map;
        for(int i=2;i*i<=p;i++)
            while(p%i==0)
                ++_map[i],p/=i;
        ++_map[p];
        int ans=1;
        for(auto &i:_map){
            int base=i.first,num=i.second;
            for(int j=1;num>0;j++){
                int now=j*base;
                ans=max(ans,now);
                while(num>0&&now%base==0)
                    now/=base,--num;
            }
        }
        cout<<ans<<"
    ";
    }
    int main()
    {
        int t;cin>>t;
        while(t--)
            solve();
        return 0;
    }
    View Code

    C. 完全图

    题意:n点完全图去掉m边后的最大连通分量。(T≤104,1≤n≤1018,1≤m≤1018

    思路:逐点去除,第一个点需要n-1条边,第二个点需要n-2条边,求得去掉n个点需要的边与m比较即可。由于数据比较大,所以需要二分查找。

    Tips:递推公式的中间值会大于long long,可以将不等式变换到long long运算的范围。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int main()
    {
        int t;cin>>t;
        while(t--){
            ll n,m;cin>>n>>m;
            ll l=0,r=n-1;
            while(l<r){
                ll mid=(l+r+1)>>1;//+1是为了防止l=r-1时的不断循环
                if(2*n-mid-1<=2*m/mid) l=mid;
                else r=mid-1;
            }
            cout<<l+1<<"
    ";
        }
        return 0;
    }
    View Code

    E. A+B问题

    题意:A和B都在32位有符号整数能存储的范围内,现在已知二者的和为c,问有多少种可能的输入数据。

    思路:很有趣的一道题,从int的底层存储考虑,每个32bit都会对应一个和为特定值的32bit,所以答案始终是4294967296。

    #include <bits/stdc++.h>
    using namespace std;
    int main()
    {
        cout<<4294967296;
        return 0;
    }
    View Code

    G. 树上求和

    题意:n点n-1边树,为每个边赋权值,使得任意两点间路径的权值和的和最小。

    思路:每个边左右点的个数之积即为该边的使用次数,将积从大到小依次赋权即可。

    #include <bits/stdc++.h>
    using namespace std;
    const int M=1e5+100;
    int n;
    vector<int> e[M];
    vector<long long> v;
    int dfs(int u,int p){
        int sum=1;
        for(int v:e[u])
            if(v!=p)
                sum+=dfs(v,u);
        v.push_back(1LL*sum*(n-sum));
        return sum;
    }
    int main()
    {
        cin>>n;
        for(int i=0;i<n-1;i++){
            int u,v;cin>>u>>v;
            --u,--v;
            e[u].push_back(v);
            e[v].push_back(u);
        }
        dfs(0,-1);
        sort(v.begin(),v.end(),greater<long long>());
        long long sum=0,num=1;
        for(auto i:v) sum+=i*num++;
        cout<<sum<<"
    ";
        return 0;
    }
    View Code

    H. 奇怪的背包问题增加了

    题意:给你一些2的幂次方,问能否凑出230,并输出选取情况。(T≤105,1≤m≤105,Σm≤105,0≤ki<30)

    思路:若当前幂次个数足够使用则选取所需,否则选取全部并继续向低幂次寻找。

    开始时用递归写的,之后简化成了非递归,前者较易实现,后者较为简洁。

    #include <bits/stdc++.h>
    using namespace std;
    const int M=1e5+100;
    int Bit[32],ans[M];
    vector<int> pos[32];
    bool flag;
    void need(int bit,int num){
        if(bit==-1){
            flag=false;
            return;
        }
        if(Bit[bit]<num){
            for(int i:pos[bit])
                ans[i]=1;
            need(bit-1,2*(num-Bit[bit]));
        }else{
            for(int i=0;i<num;i++)
                ans[pos[bit][i]]=1;
        }
    }
    void init(){
        flag=true;
        for(auto &v:pos) v.clear();
        fill(Bit,Bit+32,0);
        fill(ans,ans+M,0);
    }
    void solve(){
        init();
        int n;cin>>n;
        for(int i=0;i<n;i++){
            int t;cin>>t;
            ++Bit[t];
            pos[t].push_back(i);
        }
        need(30,1);
        if(flag) for(int i=0;i<n;i++) cout<<ans[i]<<(i==n-1?"
    ":"");
        else cout<<"impossible
    ";
    }
    int main()
    {
        int t;cin>>t;
        while(t--)
            solve();
        return 0;
    }
    View Code
    #include <bits/stdc++.h>
    using namespace std;
    const int M=1e5+100;
    void solve(){
        int Bit[32]={0},ans[M]={0};
        vector<int> pos[32];
        int n;cin>>n;
        for(int i=0;i<n;i++){
            int t;cin>>t;
            ++Bit[t];
            pos[t].push_back(i);
        }
        int bit=30,need=1;
        while(bit!=-1&&Bit[bit]<need){
            need=2*(need-Bit[bit]);
            for(int i:pos[bit]) ans[i]=1;
            --bit;
        }
        if(bit!=-1){
            for(int i=0;i<need;i++) ans[pos[bit][i]]=1;
            for(int i=0;i<n;i++) cout<<ans[i]<<(i==n-1?"
    ":"");
        }
        else cout<<"impossible
    ";
    }
    int main()
    {
        int t;cin>>t;
        while(t--)
            solve();
        return 0;
    }
    View Code

    I. 寻找子串

    题意:字符串的子串是指字符串中连续的一段,给定字符串s,请你找出字典序最大的子串。(|s|≤103

    思路:先找到字典序最大的字母,然后以该字母为首截取子串,取最大串即可。

    #include <bits/stdc++.h>
    using namespace std;
    int main()
    {
        string s;cin>>s;
        char c=*max_element(s.begin(),s.end());
        string ans;
        for(int i=0;i<s.size();i++)
            if(s[i]==c)
                ans=max(ans,s.substr(i));
        cout<<ans;
        return 0;
    }
    View Code

    J. 最大的差

    题意:给定n个数字,请你从中选出两个数字,使得这两个数字的差尽量大,输出这个最大的差。(2≤n≤105,|ai|≤105

    思路:签到题。

    #include <bits/stdc++.h>
    using namespace std;
    int main()
    {
        int n;cin>>n;
        int a[n];for(int &i:a) cin>>i;
        sort(a,a+n);
        cout<<a[n-1]-a[0];
        return 0;
    }
    View Code
  • 相关阅读:
    Mysql Explain 详解【转】
    Windows下Gradle安装与配置
    MYSQ创建联合索引,字段的先后顺序,对查询的影响分析
    给.Net 5 Api增加JwtBearer认证
    纸壳CMS 3.3.6发布升级.Net 5
    PL/SQL Developer登入时候报ORA-12638: 身份证明检索失败的解决办法
    Mybatis 日志工厂
    Mybatis 配置解析
    Mybatis 完成增删改查
    Mybatis 简介
  • 原文地址:https://www.cnblogs.com/Kanoon/p/12543390.html
Copyright © 2011-2022 走看看