Codeforces Global Round 17(A-D)

Dashboard - Codeforces Global Round 17 - Codeforceshttps://codeforces.com/contest/1610

目录

A. Anti Light's Cell Guessing

B. Kalindrome Array

C. Keshi Is Throwing a Party

D. Not Quite Lee(裴蜀定理,组合数学)


A. Anti Light's Cell Guessing

题意:有一个隐藏的格子,我们可以告诉你某个点和它的曼哈顿路径长度(|a1−a2|+|b1−b2|).问最多问几个点可以知道这个隐藏点的位置.

思路:当m==1&&n==1就只有一个点,问0次.当m,n有一个点是0时,那么只需要问一次,其余情况都需要问2次.

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N =5e5+10,mod=998244353;
void solve()
{
    int m,n;
    cin>>m>>n;
    if(m==1&&n==1)
        cout<<"0\n";
    else if(m==1||n==1)
        cout<<"1\n";
    else
        cout<<"2\n";
}
signed main()
{
    int t;
    cin>>t;
    while(t--)
       solve();
    return 0;
}

B. Kalindrome Array

Problem - B - Codeforceshttps://codeforces.com/contest/1610/problem/B题意:给你一个数字数组,是否可以删除任意个数的值等于x的数,让数组变成回文数组.

思路:我们只需要从两边往中间分别匹配,当不同时,如果题目给的条件可以成立,那么肯定是删除这两个不同数字中的一个,判断一下就行了.

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N =2e5+10,mod=998244353;
int arr[N],n;
bool check(int x)
{
    vector<int>ve;
    for(int i=1;i<=n;i++)
    {
        if(arr[i]!=x)
            ve.push_back(arr[i]);
    }
    vector<int>v1=ve;
    reverse(v1.begin(),v1.end());
    for(int i=0;i<v1.size();i++)
    {
        if(v1[i]!=ve[i])
            return false;
    }
    return true;
}
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>arr[i];
    int f=0;
    for(int i=1,j=n;i<=n,j>=0;i++,j--)
    {
        if(arr[i]!=arr[j])
        {
            f=1;
            if((check(arr[i])|check(arr[j]))==1)
            {
                cout<<"YES\n";
                return ;
            }
            else
                break;
        }
    }
    if(f)
        cout<<"NO\n";
    else
        cout<<"YES\n";
}
signed main()
{
    int t;
    cin>>t;
    while(t--)
       solve();
    return 0;
}

C. Keshi Is Throwing a Party

Problem - C - Codeforceshttps://codeforces.com/contest/1610/problem/C题意:有n个人,每个人有i元钱(第几个人就有几块钱),每个人拥有属性a,b.即为当满足最多a[i]个人比他富有,最多b[i]个人比他穷,他就是开心的,问最多选几个人满足选的这些人都是开心的.

思路:一眼二分,check函数里面就看在满足条件的情况下我选的人是否大于check的人数即可

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N =2e5+10,mod=998244353;
int n,a[N],b[N];
int check(int x)
{
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        if(b[i]>=cnt&&x-cnt-1<=a[i])
            cnt++;
//满足条件,++
    }
//cnt为理想状态我选x个人时实际上最多可以选多少人.
    if(cnt>=x)
        return 1;
    else
        return 0;
}
void solve()
{
    int ans=0;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld",&a[i],&b[i]);
    int l=1,r=n;
    while(l<r)
    {
        int mid=(l+r+1)/2;
        if(check(mid))
            l=mid;
        else
            r=mid-1;
    }    
    printf("%lld\n",l);
    return ;
}
signed main()
{
    int t;
    cin>>t;
    while(t--)
       solve();
    return 0;
}

D. Not Quite Lee(裴蜀定理,组合数学)

妙妙题.

Problem - D - Codeforceshttps://codeforces.com/contest/1610/problem/D

题意:给你n个数的数组a.当我们选择a[i]意思为我们可以选择连续的a[i]个数字的数组.比如a[i]=3,就表示我们选择了{x,x+1,x+2}(x可以为任意数字.现在要求我们选任意个数组a中的元素,并且获得他们的数组,让这些数组的元素加起来等于0.问有多少种选法.

思路:

我们对于每个数字生成的子数组进行构造,先放一个0进去,然后按照一个正数,一个负数的顺序放进去(注意数组中每个值都不能相等):{0,1,-1,2,-2,3,-3.....}.(a_{i} 个)可以得到一个结论,如果这个数是一个奇数,那么一定可以构造出结果为0的数组,偶数不一定.那么我们可以采用容斥原理,用总方案数去减去不符合条件的方案数来计算.

关于偶数,我们可以把它们构造出来的数组看做  \large \frac{a_{i}}{2}+k_{i}*a_{i}  (ki为任意数,对于枚举上面的例子很容易想到,偶数个构造数,最后肯定剩下一个a[i]/2,然后因为起点不一定是0,还要加一个不定的k*子数组的个数).

这是选出一个a数组中元素的贡献值,那么选出很多个元素的贡献就是:

\large sum=\frac{a_{1}+a_{2}+...+a_{m}}{2}+k_{1}*a_{1}+k_{2}*a_{2}+...+k_{m}*a_{m}        (m表示选了m个)

根据题意,我们要满足要求,那么sum就应该等于0.在进行移项:

\large \frac{a_{1}+a_{2}+...+a_{m}}{2}=k_{1}*a_{1}+k_{2}*a_{2}+...+k_{m}*a_{m}

一次不定方程,这种形式很容易想到裴蜀定理,要让该式子有整数解,那么根据裴蜀定理要满足:

\large gcd(a_{1},a_{2}...a_{m})|\frac{a_{1}+a_{2}+...+a_{m}}{2}        (gcd被后面的值整除)

再变形得到:

                                                                \large 2|\frac{a_{1}+a_{2}+...+a_{m}}{gcd(a_{1},a_{2}...a_{m})}

要求不符合题意的方案数,也就是不满足这个式子的组合的个数.那么当上述式子右边是奇数时,就不符合条件.

设f(x)为因子2的个数为x的元素的个数.我们在取的这些数组元素中取f(a[i])最小的值中取奇数个时,就肯定是不合法的.因为比它大的数字除以gcd之后肯定得到1,去奇数个的话加起来还是奇数,而f(a[i])比它大的元素因子比它多至少一个因子2,除以gcd之后还是偶数.

所以我们只需要在当前选择的包含有因子2的最小值中,取奇数个元素即可(这样除以2一定是奇数),

组合一下就是在n个球中取比n小的奇数的方案数,也就是\large 2^{n-1}中方案,根据乘法原理,求出f(x)最小的组合方案之后,f(x)比它大的元素无论怎么取都会保证在除以gcd之后还是偶数,又根据乘法原理,所以直接乘以后面的取法即可(因子2的数比f(x)大的元素方案数就是\large 2^{n})

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N =5e5+10,mod=1e9+7;
int num[40];
int ksm(int x,int y)
{
    int res=1;
    while(y)
    {
        if(y&1)
            res=res*x%mod;
        y>>=1;
        x=x*x%mod;
    }
    return res;
}
void solve()
{
    memset(num,0,sizeof num);
    int cnt,n,x;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        cnt=0;
        scanf("%lld",&x);
        while(x%2==0)
        {
            cnt++;
            x/=2;
        }
        if(cnt)
            num[cnt]++;
    }
    int temp,ans=0;
    for(int i=1;i<=35;i++)
    {
        if(!num[i])
            continue;
        temp=ksm(2,num[i]-1);
        for(int j=i+1;j<=35;j++)
            temp=temp*ksm(2,num[j])%mod;
        ans=(ans+temp)%mod;
    }
    printf("%lld\n",(ksm(2,n)-1-ans+mod)%mod);
    return ;
}
signed main()
{
    solve();
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值