标签:scanf 进制 info ref string mic sum def const
爆零赛总是从T1做不出来开始
T1
题面:
古代龙人手中共有n粒秘药,我们可以用1表示「古老的秘药」,其余的用0表示。他将它们排成一列。古代龙人认为平衡是美的,于是他问Mark能选出多少个「平衡的区间」。「平衡的区间」是指首先选出一个区间[L, R],在它内部选出一个中间点mid,满足L<mid<R,mid是「古老的秘药」,且区间[L, mid]和[mid, R]中「古老的秘药」个数相等。
其实就是找出有多少个区间里面有奇数个\(1\)
那么我们可以先处理出每个\(1\)的左边有多少\(0\)
然后隔一个加一个求前缀和\(sum[]\)
然后\(O(n)\)枚举左端点,用它左边的\(0\)乘右边\(sum\)的和
代码如下:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e6+10;
int ts,n,a[maxn],cnt,rt[maxn];
ll sm[2],ans=0;
int main()
{
scanf("%d%d",&ts,&n);
for(int i=1;i<=n;i++) scanf("%1d",&a[i]),cnt+=a[i];
int sum=0;
for(int i=n,j=cnt;i && j;i--){
sum++;
if(a[i]){rt[j]=sum;sum=0;j--;}
}
for(int i=1;i<=cnt;i+=2) sm[1]+=rt[i];
for(int i=2;i<=cnt;i+=2) sm[0]+=rt[i];
sum=0;
for(int i=1,j=1;i<=n;i++){
++sum;
if(a[i]){
ans+=(sum-1)*(rt[j]-1)+sum*(sm[j&1]-rt[j]);
sm[j&1]-=rt[j];j++;sum=0;
}
}
printf("%lld\n",ans);
return 0;
}
T1都不会T2更降智
T2
题面:
数据范围特别小,二进制枚举或者爆搜前一半和后半选啥就行
代码如下:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n;ll ans=0;
string s;
map<string,ll> mp;
int main()
{
scanf("%d",&n);cin>>s;
for(int i=0;i<(1<<n);i++){
string s1,s2;
for(int j=1;j<=n;j++){
if(i&(1<<(j-1))) s1+=s[j-1];
else s2+=s[j-1];
}
mp[s1+'~'+s2]++;
}
for(int i=0;i<(1<<n);i++){
string s1,s2;
for(int j=1;j<=n;j++){
if(i&(1<<(j-1))) s1=s[j+n-1]+s1;
else s2=s[j+n-1]+s2;
}
ans+=mp[s2+'~'+s1];
}
printf("%lld\n",ans/2);
return 0;
}
咕
标签:scanf 进制 info ref string mic sum def const
原文地址:https://www.cnblogs.com/ChrisKKK/p/11736151.html