CSP模拟16

CSP模拟16

T1 糖果

题意:把 n 个数分成若干段,每段异或和相等,段数大于 1 ,问能否分成。

我们从第一个数开始求数列的异或和,因为 n 大于 1 ,两个相等的数异或和为 0 ,数列异或和有两种情况:

  • 数列异或和等于 0 ,一定可以分成偶数段,符合题意。

  • 数列异或和不为 0

对于第二种情况,我们设数列异或和为 x ,异或和为 x 数列的数量为 tot ,当前异或和为 an ,我们从头开始遍历,出现一个 x 就把 tot 加一,把 an 设为零。这样就能统计出异或和为 x 的数列段数。
若段数大于 1 就符合题意。如图,空白处异或和一定为 0 ,可以并入前一段数列。

img

code

#include<iostream>
#include<cstdio>
using namespace std;
int n,a[100010];
void work(){
    scanf("%d",&n);
    int ans=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        ans^=a[i];
    }
    if(n==1){
        printf("NO\n");
        return;
    }
    if(ans==0){
        printf("YES\n");
        return;
    }
    int an=0,tot=0;
    for(int i=1;i<=n;i++){
        an^=a[i];
        if(an==ans){
            tot++;
            an=0;
        }
    }
    if(tot>1){
        printf("YES\n");
        return;
    }
    printf("NO\n");
    return ;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){work();}
    return 0;
}

T2 魔法仪式

题意:问一段数列中有多少个区间去掉区间最大值后的区间和为 k 的倍数。

我们可以二分中间值,分成两种情况考虑,一种是最大值在中间值左边,一种是最大值在中间值右边。统计非最大值的一边的区间和 % k 的值。左右两边对 k 的模的和模 k一定为 0

另外我们需要注意两种情况中只有一种可以让非最大值的那一边也出现最大值,不然会重复计算。这就是你只有30分的原因

code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define int long long
int n,k,a[300010],ans,tmp[3000010];
void work(int l,int r){
    if(l==r) return;
    int mid=(l+r)>>1;
    work(l,mid);
    work(mid+1,r);
    int ma=0,y=mid,num=0,nm2=0;
    //memset(tmp,0,sizeof(tmp));
    queue<int>q;
    for(int i=mid;i>=l;i--){
        ma=max(ma,a[i]);
        num+=a[i];
        while(a[y+1]<=ma&&y<r){
            y++;
            nm2+=a[y];
            tmp[nm2%k]++;
            q.push(nm2%k);
        }
        ans+=tmp[(k-((num-ma)%k))%k];
    }
    ma=0;int x=mid+1;num=0;nm2=0;
    while(!q.empty()){
        tmp[q.front()]=0;
        q.pop();
    }
    //memset(tmp,0,sizeof(tmp));
    for(int i=mid+1;i<=r;i++){
        ma=max(ma,a[i]);
        num+=a[i];
        while(a[x-1]<ma&&x>l){
            x--;
            nm2+=a[x];
            tmp[nm2%k]++;
            q.push(nm2%k);
            //cout<<nm2%k<<" ";
        } 
        //cout<<num-ma<<"\n";
        ans+=tmp[(k-((num-ma)%k))%k];
    }
    while(!q.empty()){
        tmp[q.front()]=0;
        q.pop();
    }
}
signed main(){
    scanf("%lld%lld",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
    }
    work(1,n);
    printf("%lld",ans);
    return 0;
}

T3 独特的数字

T4 约会

posted @   muzqingt  阅读(26)  评论(1编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示