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\n",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\n",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\n",ans);
return 0;
}
csp-s模拟46 set read race的更多相关文章
- Noip模拟46 2021.8.23
给了签到题,但除了签到题其他的什么也不会.... T1 数数 人均$AC$,没什么好说的,就是排个序,然后双指针交换着往中间移 1 #include<bits/stdc++.h> 2 #d ...
- [NOIP模拟46]鼠树
神仙题. 首先不考虑把黑点变白,发现每个白点的信息与它的归属点是相同的.可以在线段树中只维护黑点的信息,再记录$DFS$序上每个点之前黑点个数的前缀和,每次操作可以二分出该点的归属点进行操作. 具体维 ...
- CSPS模拟 46
勿忘国耻. 由于重新评测我看到了不是很真实的一幕 紧接着是更不真实的一幕 就在虚假形象快要建立完成的时候 它由于来自东方的神秘力量倒塌了 被两个学校的大佬爆踩了(捂脸 T1 无脑背包? 考试时想1h想 ...
- 8.23考试总结(NOIP模拟46)[数数·数树·鼠树·ckw的树]
T1 数数 解题思路 大概是一个签到题的感觉...(但是 pyt 并没有签上) 第一题当然可以找规律,但是咱们还是老老实实搞正解吧... 先从小到大拍个序,这样可以保证 \(a_l<a_r\) ...
- noip模拟46
A. 数数 排好序从两头贪心即可 B. 数树 首先很容易想到容斥 如果选择的边集的相关点集有点的度数大于 \(1\) 是不合法的 也就是说一定形成若干条长度不一的链 要给这些链上的点安排排列中的数,方 ...
- [考试总结]noip模拟46
脑袋确实是不好使了需要回家暴颓治疗 数数数树鼠树 真好玩. 数数 大水题一个,妥妥的签到题目,然后... 我没签上 气展了!!! 其实我还是想麻烦了. 就是我们实际上就是排序之后每一次找头上和尾巴上的 ...
- 多线程案例:龟兔赛跑-Race
多线程案例:龟兔赛跑-Race 前置条件: 首先来个赛道距离,然后要离终点越来越近 判断比赛是否结束 打印出胜利者 龟兔赛跑开始 故事中是乌龟赢了,兔子需要睡觉,所以我们来模拟兔子睡觉 乌龟赢得比赛 ...
- java基础——并发1
一.并发的定义 并发:对于这个概念一直就是没怎么搞懂,就是感觉特别的生疏,(自己从从字面上理解就是多个东西,一起出发),所以就上网上查了一些资料: 同时拥有两个或多个线程,如果程序在单核处理器上运行, ...
- 谈谈java中的并发(一)
一.并发的定义 并发:对于这个概念一直就是没怎么搞懂,就是感觉特别的生疏,(自己从从字面上理解就是多个东西,一起出发),所以就上网上查了一些资料: 同时拥有两个或多个线程,如果程序在单核处理器上运行, ...
随机推荐
- 10月23日——作业1——while循环练习
while循环'''此类编程题,注意带进去试一试1.九九乘法表row=1while row<=9: col=1 while col<=row: print(col,"*" ...
- thinkphp 闭包支持
闭包定义 我们可以使用闭包的方式定义一些特殊需求的路由,而不需要执行控制器的操作方法了,例如: 'URL_ROUTE_RULES'=>array( 'test' => function() ...
- duilib教程之duilib入门简明教程12.简单控件介绍
前面的教程应该让大家对duilib的整体有所映像了,下面就来介绍下duilib具体控件的使用. 由于官方没有提供默认的控件样式,所以我就尽量使用win7或者XP自带的按钮样式了,虽然界面比较土鳖 ...
- (转)获取android手机内部存储空间和外部存储空间的参数 && 如何决定一个apk的安装位置
转:http://blog.csdn.net/zhandoushi1982/article/details/8560233 获取android文件系统的信息,需要Environment类和StatFs ...
- VS2010-MFC(对话框:文件对话框)
转自:http://www.jizhuomi.com/software/173.html 一 文件对话框的分类 文件对话框分为打开文件对话框和保存文件对话框,相信大家在Windows系统中 ...
- json的dump和dumps的区别
dumps是将dict转化成str格式,loads是将str转化成dict格式. dump和load也是类似的功能,只是与文件操作结合起来了. In [1]: import json In [2]: ...
- Day 6:集合(set)
集合(set)定义:由不同元素组成的集合,集合中是一组无序排列的可hash值,可以作为字典的key特性:集合里面数据类型是不可变的1.可变的数据类型:列表,字典2.不可变的数据类型:数字.元组.字符串 ...
- python列表的常用操作
列表是python的基础数据类型之一 ,其他编程语言也有类似的数据类型.比如JS中的数 组, java中的数组等等. 它是以[ ]括起来, 每个元素用' , '隔开而且可以存放各种数据类型: 列表是p ...
- POJ 2187 /// 凸包入门 旋转卡壳
题目大意: 求最远点对距离 求凸包上的最远点对 挑战263页 #include <cstdio> #include <string.h> #include <algori ...
- Ubuntu环境下使用npm编译从git上clone下来的前端(Javascript)项目
一.更新Ubuntu软件源 打开终端依次输入: $ sudo apt-get update $ sudo apt-get install -y python-software-properties s ...