Codeforces Round #697 (Div. 3)

58 篇文章 0 订阅
35 篇文章 1 订阅

A. Odd Divisor

题意:判断n有没有奇数因子

思路:签到题。只有2的幂次没有奇数因子。所以一直除2就行了。

AC代码:

#include <iostream>
#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
//const int mod = 1e9+7;
const int mod = 998244353 ;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
int sel = 0;
int sum = 0;
int maxx = 0;
signed main(){
    int t;
    cin>>t;
    while(t--){
        cin>>n;
        while(n%2 == 0){
            n /= 2;
        }
        if(n != 1){
            cout<<"YES"<<endl;
        }else{
            cout<<"NO"<<endl;
        }
    }
    return 0;
}

B. New Year’s Number

题意:给定n,问能不能把n拆成 x*2020+y*2021的形式。

思路:原题可以看成是 n = (x+y)*2020 + y, y是余数。 x+y = n/2020。

AC代码:

#include <iostream>
#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
//const int mod = 1e9+7;
const int mod = 998244353 ;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
int sel = 0;
int sum = 0;
int maxx = 0;
signed main(){
    int t;
    cin>>t;
    while(t--){
        cin>>n;
        int cnt = n/2020;
        int rem = n%2020;
        if(cnt >= rem){
            cout<<"Yes"<<endl;
        }else{
            cout<<"No"<<endl;
        }
    }
    return 0;
}

C. Ball in Berland

题意:a个男的,b个女的。然后给定k对关系。x(男)可以和y(女)可以组队。让选出两对人。使得x不会出现两次,y也不会出现两次。

思路:记录x在k对中出现了多少次cnt(x)。记录y在k对中出现了多少次cnt(y)。再枚举每一对关系。如果选了这对。那还剩下 k-cnt(x)个男的,还剩下 k-cnt(y)个女的,因为选中的x,y不能再出现了嘛,但是他们自己还算一对,如果这对关系出现了多次。其实要开map记录。但是这题没有给出重复的记录。所以直接 k-cnt(x)-cnt(y)+1,就行。

AC代码:

#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
map<int,int> mp1,mp2;
map<pair<int,int>,int> mp3;
 
signed main(){
    cin>>t;
    while(t--){
        cin>>n>>m>>k;
        mp1.clear(),mp2.clear(),mp3.clear();
        for(int i = 0 ; i < k ; i ++) cin>>a[i],mp1[a[i]] ++;
        for(int i = 0 ; i < k ; i ++) cin>>b[i],mp2[b[i]] ++,mp3[{a[i],b[i]}] ++;
        int res = 0;
        for(int i = 0 ; i < k ; i ++){
            res += (k)-mp1[a[i]]-mp2[b[i]]+mp3[{a[i],b[i]}];
        }
        cout<<res/2<<endl;
    }
    return 0;
}

D. Cleaning the Phone

题意:给定两种程序列表。一种清理代价为2,一种清理代价为1。每个程序都有一个内存占用,现在要求用最小的代价清理出m的内存。

思路:首先肯定是贪心的清理同类型的程序。先清理占用内存的大的应用。所以给他们排个序。求个前缀和。然后枚举一种程序清理i个。再二分另一种程序就行了。

AC代码:

#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
map<int,int> mp1,mp2;
map<pair<int,int>,int> mp3;
int sum1[200005] = {0};
int sum2[200005] = {0};
 
signed main(){
    cin>>t;
    while(t--){
        cin>>n>>m;
        vector<int> v1;
        vector<int> v2;
        for(int i = 0 ; i < n ; i ++){
            cin>>a[i];
        }
        for(int i = 0 ; i < n ; i ++){
            cin>>b[i];
            if(b[i] == 1) v1.push_back(a[i]);
            else v2.push_back(a[i]);
        }
        sort(v1.begin(),v1.end(),greater<int>());
        sort(v2.begin(),v2.end(),greater<int>());
        for(int i = 1 ; i <= v1.size() ; i ++){
            sum1[i] = v1[i-1]+sum1[i-1];
        }
        for(int i = 1 ; i <= v2.size() ; i ++){
            sum2[i] = v2[i-1]+sum2[i-1];
        }
        int res = 1e18;
        for(int i = 0 ; i <= v1.size() ; i ++){
            int now = sum1[i];
            int need = m-now;
            int pos = lower_bound(sum2,sum2+v2.size()+1,need)-sum2;
            if(pos < v2.size()+1){
                res = min(res,i+2*(pos));
            }
        }
        if(res < 1e9) cout<<res<<endl;
        else cout<<-1<<endl;
    }
    return 0;
}

E. Advertising Agency

题意:n个博主。每个人有不同的粉丝数量。现在要和k个博主签合同。希望总的粉丝数量最大。求总方案数。

思路:贪心的去想。肯定是先选大的。前面比较大的都没得方案,全选就行了。对于最后刚好到达k时的值就是可以选择的值。比如在[1 3 1 2]选择3个,3和2,肯定是必选的。所以只能在 两个1里面选择1个。方案数就是 C 2 1 C_{2}^{1} C21,2。综上,假设最后选择的值是x。数组中有m个x。现在去点选择x 的数量,剩下还需要再选y个人。也就是在m个人里面选y个。答案为 C m y C_{m}^{y} Cmy,因为n比较小。直接暴力算组合数就好了。

AC代码:

#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
map<int,int> mp1,mp2;
map<pair<int,int>,int> mp3;
int sum1[200005] = {0};
int sum2[200005] = {0};
 
int cal(int x,int y){
    int res = 1;
    for(int i = 0 ; i < y ; i ++){
        res = (res*x)%mod;
        x -= 1;
    }
    return res;
}
 
int qpow(int a,int b){
    int res = 1;
    int tmp = a;
    while(b) {
        if(b&1) res =res*tmp %mod;
        b>>=1;
        tmp = tmp*tmp%mod;
    }
    return res;
}
 
signed main(){
    cin>>t;
    while(t--){
        cin>>n>>m;
        map<int,int> mp;
        for(int i = 0 ; i <n ; i ++) cin>>a[i],mp[a[i]] ++;
        sort(a,a+n,greater<int>());
        int last = a[m-1];
        int need = m;
        for(int i = 0 ; i < n ; i ++){
            if(a[i] == last) break;
            need --;
        }
        int res = (cal(mp[last],need)*qpow(cal(need,need),mod-2))%mod;
        cout<<res<<endl;
    }
    return 0;
}

F. Unusual Matrix

题意:一个01矩阵a和另一个01矩阵b。有两种操作,一种是选择一列全部异或上1,一种是选择一行全部异或上1。问能不能把a变成b。

思路:因为都是n*n的矩阵,可以这样想。先把左上角的一个点变成和b一样的。然后向外拓展一行和一列。也就是左上角2*2的矩阵。这样可以保证。已经修改过的点就不再修改了。直到全部修改完。如果一样那就是一样了。如果不一样,那也改不回来了。一个点如果不一样,改变一次就可以了。再改变一次就没有意义了。

AC代码:

#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[1005][1005],b[1005][1005];
string s1[N];
string s2[N];
 
signed main(){
    cin>>t;
    while(t--){
        cin>>n;
        m = n;
        for(int i = 0 ; i < n ; i ++){
            cin>>s1[i];
            for(int j = 0 ; j < m ; j ++){
                a[i][j] = s1[i][j] - '0';
            }
        }
        for(int i = 0 ; i < n ; i ++){
            cin>>s2[i];
            for(int j = 0 ; j < m ; j ++){
                b[i][j] = s2[i][j] - '0';
            }
        }
        for(int i = 0 ; i < n ; i ++){
            if(a[i][0] != b[i][0]){
                for(int j = 0 ; j < n; j ++){
                    a[i][j] ^= 1;
                }
            }
            if(a[0][i] != b[0][i]){
                for(int j = 0 ; j < n; j ++){
                    a[j][i] ^= 1;
                }
            }
        }
        int res = 1;
        for(int i = 0 ; i < n ; i ++){
            for(int j = 0 ; j < m ;  j ++){
                if(a[i][j] != b[i][j]){
                    res = 0;
                }
            }
        }
        puts(res ? "YES" : "NO");
    }
    return 0;
}

G. Strange Beauty

题意:给定一个数组。要使得数组中任意两个数存在倍数关系。至少要删掉几个数。

思路:可以反过来想。枚举一个数。可以求出数组中和这个数是倍数关系的数最多是多少个,然后用n减去它不就是答案了嘛。所以先对数组排个序。然后从小到大,枚举数组的数。用dp数组记录。以当前这个数作为终点的序列有多长。什么意思呢。比如,1,2,4,8。dp[1] = 1;dp[2] = 2; dp[4] = 3; dp[8] = 4; 然后就要保证 前面所有的数都跟他是倍数关系。假设当前数是x。把x当成是序列的倒数第二个数。用dp[x] 去更新 x 的所有倍数。dp[j] = max(dp[j],dp[x])

AC代码:

#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[N];
int dp[N];
 
signed main(){
    cin>>t;
    while(t--){
        cin>>n;
        map<int,int> mp;
        int maxx = 0;
        for(int i = 0 ; i < n ; i ++){
            cin>>a[i];
            mp[a[i]] ++;
            maxx = max(maxx,a[i]);
        }
        for(int i = 1; i <= maxx; i ++) dp[i] = 0;
        int res = 0;
        for(int i = 1; i <= maxx; i ++){
            dp[i] += mp[i];
            for(int j = i*2; j <= maxx ; j += i){
                dp[j] = max(dp[j],dp[i]);
            }
            res = max(res,dp[i]);
        }
        cout<<n-res<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值