牛客题集:练习赛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; }
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\n",m*(m-1)%mod*qpow(2,mod-2)%mod*qpow(m,n-2)%mod*(n-1)%mod*3%mod); } return 0; }
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; }