Codeforces Round #774 (Div. 2)(A--C)

本文介绍了三个算法题目,分别是A.SquareCounting、B.Quality vs Quantity和C.Factorials and Powers of Two。A题通过计算(n*n)/s得到答案;B题利用排序和双指针策略解决染色问题;C题通过位运算判断数是否能由阶乘和2的次幂构成。文章展示了C++实现的解题代码,并提供了每道题目的思路总结。
摘要由CSDN通过智能技术生成

A. Square Counting

题意:

给出一个长度为n的数组和数组的和S,构成数组的数要么是从0~n,要么是n*n,求n*n的个数最多是多少个

思路:

默认全是(n*n),那么算个数就直接(n*n)/s

#include<bits/stdc++.h>

using namespace std;

int main()
{
    long long  n,i,j,t,s;
    cin>>t;
    while(t--)
    {
        cin>>n>>s;
        //s/(n*n)
        cout<<s/(n*n)<<endl;
    }
    return 0;
}

B. Quality vs Quantity

题意:

给出一个长度为n的数组,现在进行染色,可以选择染为红色,蓝色或者不染,问是否可以染色完数组后染色数量少的一方,相加的值大于染色数量多的一方

思路:

可以通过前缀和算,我是排序之后,双指针一个从左边取,一个从右边取。

#include<bits/stdc++.h>

using namespace std;

const int maxn=2e5+1000;
int a[maxn], b[maxn];
int main()
{
    int n,i,j,t;
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(i=0;i<n;i++){
            cin>>a[i];
        }
        sort(a,a+n);
        long long ans1=0,ans2=0,flag=0;
        vector<int >b1,b2;
        b2.push_back(a[n-1]);
        ans2+=a[n-1];
        j=n-2;
        for(i=0;i<n;i++){
            ans1+=a[i];
            b1.push_back(a[i]);
            while(ans2<=ans1&&j>i)
            {
                ans2+=a[j];
                b2.push_back(a[j]);
                j--;
            }
            if(ans2>ans1&&b2.size()<b1.size())
            {
                flag=1;
            }
        }
        if(flag==0){
            cout<<"No"<<endl;
        }else {
            cout<<"Yes"<<endl;
        }
    }
    return 0;
}
/*
我要选两组数,且第一组的数量小于第二组并且第一组的和大于第二组
第一组肯定先选最大的a[n-1],第二组选两个小的,如果第二组比第一组大,再双指针不停选,总和2e5
应该不会t,处理好就是O(n)的复杂度了

7
3
1 2 3
5
2 8 6 3 1
4
3 5 4 2
5
1000000000 1000000000 1000000000 1000000000 1000000000
5
3 5 6 8 7

*/

C. Factorials and Powers of Two

题意:

问一个数n能否全部由2的次幂或者n的阶乘构成,且构成n的数都得不相同

思路:

  1. 首先d!如果是小于1e12,那么最多只会有15种,又因为构成n的阶乘数和2的次方的数必须是不相同的
  2. 所以可以先枚举n的阶乘,这里使用状态压缩,因为每种数都有选择和不选两种方案,又因为最多就16个数
  3. 所以应该是有2^16次方种方案,再用位运算算出取1的时候就是选这个数,最后加起来如果是小于等于n的
  4. 再去求2的n次方,这个容易求直接使用位运算算剩下的数字里转为成2进制1的个数即可
  5. 最后把个数加起来取最小值
#include<cstdio>
#include<algorithm>
using namespace std;
int t;
long long n,fac[20];
int BitCount(long long x)
{
    int res=0;
    while(x)
    {
        res+=(x&1);
        x>>=1;
    }
    return res;
}
int main()
{
    fac[0]=1;
    for(int i=1;i<=15;i++) fac[i]=fac[i-1]*i;
    int tot=(1<<16);
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld",&n);
        int ans=1000;
        for(int i=0;i<tot;i++)
        {
            long long tmp=0;
            int cnt=0;
            for(int j=0;j<=15;j++)
            {
                if(i & (1<<j)) 
                {
                    tmp+=fac[j];
                    cnt++;
                }
            }
            if(tmp<=n) ans=min(ans,BitCount(n-tmp) + cnt);
        }
        printf("%d\n",ans);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值