Codeforces Round #565 (Div. 3)

A. Divide it!

题意:满足下面的条件,输出替换后的最小的数,反之输出-1。

暴力

#include <bits/stdc++.h>
#include <iostream>
 
using namespace std;
 
const int maxn=2e4+5;
//int a[maxn][maxn];
#define  ll long long
 
int main(){
    int n;
    cin>>n;
    while(n--){
        ll m;
        cin>>m;
        int ans=0;
        while(m!=1){
            ans++;
            if(m%2==0) m/=2;
            else if(m%3==0) m=m/3*2;
            else if(m%5==0) m=m/5*4;
            else {
                ans=-1;
                break;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
View Code

 

B - Merge it!

题意:通过合并一些数,使得能被3整除的最多个数是多少。

想的深入一点,会发现其实可以变成只包含1,2序列,将数组预处理%上3,找出能被3整除的,然后把得到的只包含1,2的序列合并成3就简单多了,加上这里合并出来的3就是答案了

 

#include <bits/stdc++.h>
#include <iostream>
 
using namespace std;
 
const int maxn=2e4+5;
int a[maxn];
#define  ll long long
//sync_with_stdio (false);
int main(){
    int n,m;
 
    cin>>n;
    while(n--){
        cin>>m;
        int index=0;
        for(int i=0; i<m; i++){
            int x=0;
            cin>>x;
            if(x%3!=0) a[index++]=x%3;
        }
        int ans=m-index;
        int y1=0,y2=0;
        for(int i=0; i<index; i++){
            if(a[i]==1) y1++;
            else y2++;
        }
        if(y1>=y2){
            ans+=(y2+(y1-y2)/3);
        }
        else ans+=(y1+(y2-y1)/3);
        cout<<ans<<endl;
    }
    return 0;
}
View Code

 

C - Lose it!

题意:删除最少的元素,使的数组中的元素都是由下面的序列组成的,换句话说:该序列包含了n个该子序列

4,8,15,16,23,42

题目看错,反应过来,dp写错,不是42元素前面有4,8,15,16,23元素,而是要有这个序列,是顺序要求的 qwq

wa了的代码:

#include <bits/stdc++.h>
#include <iostream>
 
using namespace std;
 
const int maxn=2e4+5;
int a[50];
#define  ll long long
//sync_with_stdio (false);
int main(){
    memset(a,0,sizeof(a));
    int n,m=600000;
    cin>>n;
    int ans=0;
    for(int i=0; i<n; i++){
        float x;
        cin>>x;
        if(x/4==1) a[0]++;
        else if(x/8==1) a[1]++;
        else if(x/15==1) a[2]++;
        else if(x/16==1) a[3]++;
        else if(x/23==1) a[4]++;
        else if(x/42==1) a[5]++;
        if(x==42){
            if(a[0]>0&&a[1]>0&&a[2]>0&&a[3]>0&&a[4]>0&&a[5]>0){
            a[0]--,a[1]--,a[2]--,a[3]--,a[4]--,a[5]--;
            ans++;
            }
        }
    }
    ans=n-ans*6;
    cout<<ans<<endl;
    return 0;
}
View Code

简单dp(ac)

#include <bits/stdc++.h>
#include <iostream>
 
using namespace std;
 
const int maxn=2e4+5;
int a[50];
map<int,int> mp;
#define  ll long long
//
int main(){
    std::ios::sync_with_stdio (false);
    memset(a,0,sizeof(a));
    mp[4]=0,mp[8]=1,mp[15]=2,mp[16]=3,mp[23]=4,mp[42]=5;
    int n,m=600000;
    cin>>n;
    int ans=0;
    for(int i=0; i<n; i++){
        int x;
        cin>>x;
        int index=mp[x];
        if(mp[x]==0||a[index-1]>a[index]) a[index]++;
 
    }
    //cout<<ans<<endl;
    ans=n-a[5]*6;
    cout<<ans<<endl;
    return 0;
}
View Code

 

E - Cover it!

题意:删除一些点,不超过总数的一半,使剩下的点和至少和一个删除的点有一天边。

开始时,一句关键的画没看懂,把题目读偏了,看了一下别人的题解,有人说是二分图,其实不是的,只是做法有些类似,用dfs把相邻边染成不同颜色,但其实这里相邻点可以是相同颜色,只有当相邻点颜色不同时,才时二分图,其实这也是二分图的判定方法。

dfs时O(n),还有n组数据,时间复杂度时O(n*n);2秒,应该会T啊,是数据水了吗qwq

#include <bits/stdc++.h>
#include <iostream>
 
using namespace std;
 
#define  ll long long
const int maxn=2e5+5;
 
//int a[maxn],tmp[maxn];
pair<int,int> p;
map<int,int> mp;
//map<int,int> ::iterator it;
//vector<pair<int,int> >::iterator its;
vector<int> edge[maxn];
bool vis[maxn];
set<int> a,b;
set<int> ::iterator it;
 
void dfs(int u,int flag){
    vis[u]=1;
    if(flag) a.insert(u);
    else b.insert(u);
    for(int i=0; i<edge[u].size(); ++i){
        if(!vis[edge[u][i]]) {
            dfs(edge[u][i],!flag);
        }
    }
}
void init(int n){
    a.clear(),b.clear();
    for(int i=1; i<=n; ++i) edge[i].clear(),vis[i]=0;
}
int main(){
    std::ios::sync_with_stdio (false);
    int q,n,m,u,v;
    cin>>q;
    while(q--){
        cin>>n>>m;
        init(n);
        for(int i=0; i<m; ++i){
            cin>>u>>v;
            edge[u].push_back(v),edge[v].push_back(u);
        }
        dfs(1,1);
        if(a.size()>b.size()){
            cout<<b.size()<<"\n";
            for(it=b.begin(); it!=b.end(); ++it) cout<<*it<<" ";
            cout<<"\n";
        }
        else{
            cout<<a.size()<<"\n";
            for(it=a.begin(); it!=a.end(); ++it) cout<<*it<<" ";
            cout<<"\n";
        }
    }
    return 0;
}
View Code

 

D - Recover it!

题意:进行下面的操作,将的得到的a[n],b[n]数组混合,要你还原出a[n]数组

素数筛,求最大共因数,排一下序,从大到小扫一遍,如果是因数,找到其是第几个素数(map映射),加入a数组中,并将其从b中出去(我是用map处理的);如果不是因数,把它加入a,从b中删除其最大的因数(map处理)

注意:一定要处理那些b中不是a中的数

这里求最大公因数的 最快方法是能被整除的最小质数的那个数(有点虚)

#include <bits/stdc++.h>
#include <iostream>
 
using namespace std;
 
#define  ll long long
const int maxn=4e5+5;
 
//int a[maxn],tmp[maxn];
pair<int,int> p;
map<int,int> mp;
map<int,int> mpp;
map<int,int> ::iterator it;
//vector<pair<int,int> >::iterator its;
//ll mod=1e9+7;
struct edge{
    ll v;
    ll du;
};
int a[maxn];
bool cmp(int a,int b){
    return a>b;
}
bool prime[2750131+5];
void getprime(){
    int index=0;
    for(int i=2; i*i<2750131+5; ++i)
    if(!prime[i]) {
        for(int j=i*i; j<2750131+5; j+=i) prime[j]=1;
    }
    for(int i=2; i<=2750131; ++i) if(!prime[i]) mp[i]=++index;
}
ll mulit(ll base,ll k ,ll mod){
    ll ans=1;
    while(k){
        if(k%2) ans=base*ans%mod;
        base=base*base%mod;
        k>>=1;
    }
    return ans%mod;
}
ll sub(ll a, ll b, ll mod){
    ll ans=a-b;
    if(ans<0) ans+=mod;
    return ans;
}
 
int main(){
    std::ios::sync_with_stdio (false);
    int t,n,m,v,u;
    cin>>n;
    getprime();
    for(int i=0; i<2*n; ++i) cin>>a[i];
    sort(a,a+2*n,cmp);
    int ans=0;
    for(int i=0; i<2*n; ++i){
        if(prime[a[i]]) {
            if(mpp[a[i]]>0){
                --mpp[a[i]];
                continue;
            }
            cout<<a[i]<<" ";
            ++ans;
            for(it=mp.begin(); it!=mp.end(); ++it)
            if(a[i]%(it->first)==0){
                ++mpp[a[i]/(it->first)];
                break;
            }
        }
        else{
            if(mpp[a[i]]==0){
                cout<<mp[a[i]]<<" ";
                ++mpp[mp[a[i]]];
                ++ans;
            }
            else --mpp[a[i]];
        }
        if(ans==n) break;
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/mrdushe/p/11154881.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值