Codeforces Round #774 (Div.2)

A. Square Counting

Description

Luis 有一个长为 \((n+1)\) 的整数序列 \(a\),保证 \(\forall i\in[1,n+1]\)\(0\le a_i<n\)\(a_i=n^2\),记 \(s=\sum_{i=1}^{n+1}a_i\)。现在 Luis 丢了这个序列,但是还留下 \(n\)\(s\),求序列中有几个数的值为 \(n^2\)

Solution

明显地,答案就是 \(\bigg\lfloor\dfrac s{n^2}\bigg\rfloor\),也就是说,能放下几个 \(n^2\) 就放下几个 \(n^2\),剩下的 \(s\bmod n^2\) 一定能够将其他数字填充进去,因为 \(s\bmod n^2<n^2\),而剩下所有数和的最大可能值为 \((n-1)(n+1)=n^2-1\),不用担心不够填充。

单次询问时间复杂度 \(O(1)\)

Code

记得要开 long long

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        long long n,s;
        scanf("%lld%lld",&n,&s);
        printf("%lld\n",s/(n*n));
    }
    return 0;
}

B. Quality vs Quantity

Description

有一个长为 \(n\) 的非负整数数列 \(a\),将里面的数涂成红色 或者 蓝色。问是否有可能红色数的数量小于蓝色数的数量且红色数的总和大于蓝色数的总和。

Solution

必须的,我们要把 \(a\) 从小到大排序。每次我们枚举蓝色数的数量 \(i\),为了使红色数的总和尽可能的大,我们令红色数的数量为 \((i-1)\),且取的就是最大的 \((i-1)\) 个数,而蓝色数取的就是最小的 \(i\) 个数,一直枚举到两种颜色有交集,只要出现红色数的总和大于蓝色数的总和即 \(\sum_{j=n-i+2}^na_j>\sum_{j=1}^ia_j\),输出 YES,若一直没有,则输出 NO

单次询问时间复杂度 \(O(n\log n)\)

Code

依然要开 long long

#include<bits/stdc++.h>
using namespace std;
int a[200005];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        long long x=a[1]+a[2],y=a[n];
        bool flag=x<y;
        for(int i=3;i<n-i+2;i++)
        {
            x+=a[i];
            y+=a[n-i+2];
            if(x<y) flag=1;
            if(flag) break;
        }
        if(flag) puts("YES");
        else puts("NO");
    }
    return 0;
}

C. Factorials and Powers of Two

Description

定义一个数为 强大的 当其可以被写成 \(2^d\)\(d!\) 的形式(\(d\in\mathbb N_+\))。特别的,\(0!=1\)。现给出一个正整数 \(n\),问 \(n\) 最少能够拆解为几个不同的强大的数的和。若不能拆解,输出 -1

Solution

为了方便,此处定义阶乘的反函数为 \(\operatorname{arcfac}(x)\)

题目给出的范围为 \(n\le10^{12}\),而 \(\big\lfloor\log10^{12}\big\rfloor=39\)\(\big\lfloor\operatorname{arcfac}(10^{12})\big\rfloor=14\),其中 \(2^0=0!=1!=1\)\(2^1=2!=2\),所以在数据范围内不同的强大的数有 \(39+14-2-1=50\) 个。如果我们全部暴力 dfs 肯定是不行的。但是发现阶乘数却只有 \(14\) 个,如果只枚举阶乘数,是可以过的。

事实上,一个自然数 \(x\) 能被 \(\operatorname{bitcount}(x)\) 个不同的 \(2\) 的整数幂分解,其中 \(\operatorname{bitcount}(x)\)\(x\) 的二进制表示中 \(1\) 的个数。这是显而易见的。于是我们可以枚举阶乘数,将余下的部分求 \(\operatorname{bitcount}\),求得每一种方案的分解数,最后去最小值即可。

单次询问时间复杂度为 \(O(2^{\operatorname{arcfac}(n)}\log n)\)

Code

还是要开 long long

#include<bits/stdc++.h>
using namespace std;
long long n,fac[20];
int ans;
inline int bitcount(long long x)
{
    int tot=0;
    while(x)
    {
        tot+=x&1;
        x>>=1;
    }
    return tot;
}
inline void dfs(int pos,long long sum,int chosen)
{
    if(sum+fac[pos]>n||pos==16)
    {
        ans=min(ans,chosen+bitcount(n-sum));
        return;
    }
    dfs(pos+1,sum,chosen);
    dfs(pos+1,sum+fac[pos],chosen+1);
}
int main()
{
    fac[0]=1;
    for(int i=1;i<=15;i++) fac[i]=fac[i-1]*i;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld",&n);
        ans=100;
        dfs(0,0,0);
        printf("%d\n",ans);
    }
    return 0;
}

D~F 题鉴于我太菜了,就不写了,也写不出来。

posted @ 2022-03-06 16:10  ryanright  阅读(95)  评论(0)    收藏  举报