牛客小白月賽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")<<"\n";
}
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<<"\n";
}
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<<"\n";
    }
    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<<"\n";
    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?"\n":"");
    else cout<<"impossible\n";
}
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?"\n":"");
    }
    else cout<<"impossible\n";
}
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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM