T1024模拟赛

T1024

T1

爆零赛总是从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;
}

T2

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;
}

T3

posted @ 2019-10-25 08:47  ChrisKKK  阅读(620)  评论(0编辑  收藏  举报