B、左右互博
不能操作的情况有且仅有所有石子堆的石子个数只有1的时候,因此不管途中怎么操作,让所有石子堆都变成1的总操作次数是确定的。
即假设一共有\(n\)堆石子,石子总数为\(sum\),总操作次数为\((sum-n)\)次。
因此当\((sum-n)\)%\(2=0\)时一定在sweet操作完(或没有操作)后gui无法操作,sweet胜利;反之gui胜利。
时间复杂度:\(O(n)\)
c++
ac代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
const int inf=1e18;
const int M=1e9+7;
int a[N];
signed main() {
int n;
int cnt=0;
cin >>n;
for(int i=1;i<=n;i++)
{
cin >>a[i];
cnt+=a[i];
}
if((cnt-n)%2==0)
cout<<"sweet"<<'\n';
else cout<<"gui"<<'\n';
return 0;
}
E、漂亮数组
只要一段内出现过相加为\(k\)的倍数连续段,就直接在那段后面分割即可保持数量最大,那现在的问题就是如何去判断某段内有没有出现过相加和为\(k\)的倍数的连续段。
用\(sum\)数组记录数组前缀和,变量\(now\)记录当前隔板(即上一次分割的位置),如果在当前段中出现了模\(k\)的相同值或者本身这一段的和就是\(k\)的倍数,就说明出现了相加为\(k\)的倍数的连续段,一段内的模\(k\)值可用\(map\)记录。分割完更新隔板位置,继续往后判断即可。
因为题意问的是分割后的漂亮数组数量,那就不用管其他多余段的情况,因为分割了多少刀本质上就是分出了多少个漂亮数组。
时间复杂度:\(O(nlogn)\)
c++
标签:const,int,题解,sum,石子,long,补题,数组,集训营
From: https://www.cnblogs.com/ritsuki27/p/18031596
ac代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
const int inf=1e18;
const int M=1e9+7;
map<int,int> mp;
int a[N];
int sum[N];
signed main() {
int n,k;
cin >>n>>k;
for(int i=1;i<=n;i++)
{
cin >>a[i];
sum[i]=sum[i-1]+a[i];
}
int now=0;
int ans=0;
for(int i=1;i<=n;i++)
{
if(mp[(sum[i]-sum[now])%k]!=0||(sum[i]-sum[now])%k==0)
{
ans++;
mp.clear();
now=i;
}
else
mp[(sum[i]-sum[now])%k]++;
}
cout<<ans<<'\n';
return 0;
}