牛客题集:练习赛76

前段时间发现牛客这些比赛质量挺高的,打算寒假期间补一补

A

直接枚举每个小组对游戏的了解程度,然后每个人从前到后连着组队,如果当前队伍了解程度刚好等于枚举的了解值,说明能够组成一队,后面的人再自行一一组队,否则,当前枚举值不符合条件。

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double lf;
typedef pair<ll, ll> pii;
const int maxn = 1e6+10;
const int N = 1500+10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
const int hash_num = 131;
const double eps=1e-6;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
int n,a[maxn],cur,i,cnt,j,sum,ans;
char s[maxn];
int main()
{
    n=read();
    scanf("%s",s+1);
    for (i=1;i<=n;i++) a[i]=s[i]-'0';
    for (i=1;i<=n;i++) sum+=a[i];
    ans=-1;
    for (i=0;i<=sum;i++)
    {
        if (i!=0&&sum%i!=0) continue;
        cnt=0;cur=0;
        for (j=1;j<=n;j++)
        {
            cur+=a[j];
            if (cur==i)
            {
                ++cnt;cur=0;
            }
            else if (cur>i) 
            {
                cnt=-1;
                break;
            }
        }
        if (cnt>1)
            ans=max(ans,cnt);
    }
    cout<<ans<<endl;
    return 0;
}
View Code

C

每个位置,都有m种选择,假设当前取 j,则对于前一位来说有 j-1个比它小,m-j 个比它大。 所以贡献为 ( j − 1 ) + 2 ∗ ( m − j ) 。

又因为每个位置贡献只取决于第i位和第i-1位,所有每个位置都需要乘

最后统计第2~n位置的贡献之和,即可得到式子

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double lf;
typedef pair<ll, ll> pii;
const int maxn = 1e3+10;
const int N = 1500+10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
const int hash_num = 131;
const double eps=1e-6;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
ll t,n,m;
int main()
{
    t=read();
    while (t--)
    {
        n=read(),m=read();
        printf("%lld
",m*(m-1)%mod*qpow(2,mod-2)%mod*qpow(m,n-2)%mod*(n-1)%mod*3%mod);
    }
    return 0;
}
View Code

E

线性基+二分

线性基找第x小,这个x就由二分枚举得到,我们最终找到的x值是第一个大于k的值,答案容斥一下即可得到

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double lf;
typedef pair<ll, ll> pii;
const int maxn = 1e6+10;
const int N = 1500+10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
const int hash_num = 131;
const double eps=1e-6;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
struct basis{
    static const int n=63;
    #define B(x,i) ((x>>i)&1)
    ll a[n],sz;
    bool failpush; //是否线性相关
    void init(){memset(a,0,sizeof(a));sz=failpush=0;}
    void push(ll x){ //插入元素
        for (int i=0;i<n;i++)
            if(B(x,i))x^=a[i];
        if(x!=0){
            int p=63-__builtin_clzll(x); sz++;
            for (int i=p+1;i<n;i++)
                if(B(a[i],p))a[i]^=x;
            a[p]=x;
        }
        else failpush=1;
    }
    ll top(){ //最大值
        ll ans=0;
        for (int i=0;i<n;i++) ans^=a[i];
        return ans;
    }
    ll kth(ll k){ //第k小,不存在返回-1
        if(failpush)k--; //如果认为0是可能的答案就加这句话
        if(k>=(1ll<<sz))return -1;
        ll ans=0;
        for (int i=0;i<n;i++)
        if(a[i]!=0){
            if(k&1)ans^=a[i];
            k>>=1;
        }
        return ans;
    }
}b;
int n,i;
ll x,k;
int main()
{
    n=read(),k=read();
    b.init();
    for (i=1;i<=n;i++) 
    {
        x=read();
        b.push(x);
    }
    ll l=1,r=(1ll<<b.sz)+b.failpush-1;
    while (l<r)
    {
        ll mid=(l+r)>>1;
        if (b.kth(mid)>k) r=mid;
            else l=mid+1;
    }
    cout<<(1ll<<b.sz)-l+b.failpush<<endl;
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Y-Knightqin/p/14339388.html