• csp-s模拟46 set read race


    题面:https://www.cnblogs.com/Juve/articles/11556809.html

    Set:

    题干中说的M个数两两不同是说不能重复选同一个位置的数,而不是不能选数值相同的数,所以不用取重

    题目中说是子集,其实连续的序列中就有答案

    我们处理出mod N下的前缀和,如果有两个前缀和相同,那么选这两个前缀和中间的数即可,因为减完之后余数为0

    这样一定能保证正确吗?或者一定存在两个前缀和相等的情况吗?

    在mod N先前缀和最多有0~N-1这N种取值,但是一共有N+1个前缀和(sum[0]也算一种),所以一定有答案

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define MAXN 1000005
    #define re register
    using namespace std;
    int n,sum[MAXN],a[MAXN],pos[MAXN];
    inline int read(){
    	re int x=0;re char ch=getchar();
    	while(ch<'0'||ch>'9') ch=getchar();
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x;
    }
    signed main(){
    	n=read();
    	for(re int i=1;i<=n;++i){
    		a[i]=read();
    		sum[i]=(sum[i-1]+a[i]%n)%n;
    		if(!pos[sum[i]]) pos[sum[i]]=i;
    		else{
    			re int j=pos[sum[i]];
    			printf("%d
    ",i-j);
    			for(re int p=j+1;p<=i;++p){
    				printf("%d ",p);
    			}
    			puts("");
    			return 0;
    		}
    	}
    	return 0;
    }
    

    Read:

    一个显然的结论,设数量最多的书出现的次数为k,那么答案就是max(0,2×k-n-1)

    但是题目卡空间,不能存下,所以我们要想顺序访问每一个元素就让它从新生成一遍

    先扫第一遍,记录一个cnt和id,如果cnt=0,那么cnt=1,id=a[i],

    如果id=a[i],cnt++,如果不等,cnt--,那么最终留下的id就是出现次数最多的

    然后再扫一遍统计id出现次数即可

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define re register
    using namespace std;
    const int MAXN=1005;
    int n,m,k,cnt[MAXN],x[MAXN],y[MAXN],z[MAXN],S,id=0,sum=0,ans;
    signed main(){
    	scanf("%d%d",&m,&k);
    	for(int i=1;i<=m;++i) scanf("%d",&cnt[i]);
    	for(int i=1;i<=m;++i) scanf("%d",&x[i]);
    	for(int i=1;i<=m;++i) scanf("%d",&y[i]);
    	for(int i=1;i<=m;++i) scanf("%d",&z[i]);
    	S=(1<<k)-1;
    	for(int i=1;i<=m;++i){
            if(sum==0) id=x[i],sum=1;
            else if(id==x[i]) ++sum;
            else --sum;
    		long long last=x[i];
    		for(int j=1;j<cnt[i];++j){
    			last=(last*y[i]+z[i])&S;
                if(sum==0) id=last,sum=1;
                else if(id==last) ++sum;
                else --sum;
    		}
    	}
        sum=0;
        for(int i=1;i<=m;++i){
            n+=cnt[i];
            if(x[i]==id) ++sum;
    		long long last=x[i];
    		for(int j=1;j<cnt[i];++j){
    			last=(last*y[i]+z[i])&S;
                if(last==id) ++sum;
    		}
    	}
    	ans=max(0,sum*2-n-1);
        printf("%d
    ",ans);
    	return 0;
    }
    

    Race:

    考虑怎么求出 x 的答案 . 平方相当于是枚举两个人 ( 可以相同 ), 把这两个人同时排在 x 前面的天数计入答案 . 那么对于 x, 如果我们求出 f[i] 也就是能力值的二进制中第 i+1 到 M-1 位都和他相等且第 i 位不同的人有多少个 , 那么这些人是否排在他前面只由第 i 位确定 , 一共有 2^(M-1) 天 , 而且不需要从这些人中枚举两个人了 , 因为直接平方即可 . 我们只要枚举 i 和 j, f[i] 这些人和 f[j] 这些人同时排在他前面的天数为2^(M-2), 所以把 2*f[i]*f[j]*2^(M-2) 计入答案 . 具体实现有很多方法 , 可以用 trie 树实现 ,记录trie上每一个节点被访问过的次数,在扫每一个a[i]时,它的f数组就是在当前二进制位上与他这一位相反的数被经过的次数,对于tr[root][p]和tr[root][p^1],因为要xor从0到2M-1,所以当前位xor出与他相反的次数是tr[root][p],和它相同的是tr[root][p^1].

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    #define int long long
    #define re register
    using namespace std;
    const int MAXN=6000005;
    const int mod=1e9+7;
    int n,m,tot=1,ans=0,a[MAXN],f[MAXN];
    int tr[MAXN][2],s[MAXN*2];
    void insert(int val){
    	int root=1;
    	for(int i=m-1;i>=0;--i){
    		int p=(val>>i)&1;
    		if(!tr[root][p]) tr[root][p]=++tot;
    		++s[tr[root][p]];
    		root=tr[root][p];
    	}
    }
    int query(int val){
    	int res=0,root=1;
    	for(int i=m-1;i>=0;--i){
    		int p=(val>>i)&1;
    		f[i]=s[tr[root][p^1]];
    		for(int j=i;j<m;++j) (res+=(f[i]*f[j])%mod)%=mod;
    		root=tr[root][p];
    	}
    	return (res<<(m-1))%mod;
    }
    signed main(){
    	scanf("%lld%lld",&n,&m);
    	for(re int i=1;i<=n;++i){
    		scanf("%lld",&a[i]);
    		insert(a[i]);
    	}
    	for(int i=1;i<=n;++i){
    		ans^=query(a[i]);
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    MySQL讲义
    python使用matplotlib在一个图形中绘制多个子图以及一个子图中绘制多条动态折线问题
    python爬虫登陆网页版腾讯课堂
    父子组件之间相互传值
    echarts图中使用到的属性及对应的作用,饼图实例、折线图实例
    vue get类型接口调用方式
    javaScript前进后退点击事件
    vue页面跳转
    如何修改vant组件中原有样式?
    Module not found: Error: Can't resolve 'less-loader' in '文件位置'报错解决
  • 原文地址:https://www.cnblogs.com/Juve/p/11556951.html
Copyright © 2020-2023  润新知