吐槽&记录
人生真是很多意想不到的事情,来的第一天去搞事,跑遍整个沈阳市郊,有个万达,附近的internet bar好少,而且普遍进不去,后来颓了一下午,把营员证搞掉,晚上吃的外卖,真难吃,本来说要开开营仪式,结果衡水的没来(大佬还没来),所以就不开了。晚自习的时候已经有大神在装逼了,初三的学弟虐场,回寝室的,浴室环境很差,完全可以用来拍鬼片,没买拖鞋,用麦当劳的装可乐的塑料袋当了一次拖鞋,晚上晚自习的时候就想着回去一定要好好休息,明天的题应该不会太难,要好好发挥,结果回寝室有长春十一中的大佬开热点,于是用流量打了局lol,卡到人物在地上磨着走,然后陪室友打cs到深夜,半死半活地睡去,已经有室友在打鼾了
第二天丧心病狂的有人在五点钟闹铃(前一天赶飞机),被闹醒后半个小时睡不着,然后刚睡了一会儿,有个人6点的闹铃又响了,时候他说是他故意不关的(想打他),然后在床上翻来覆去躺了二十分钟,六点二十起床,六点五十去食堂,食堂上面有四个大字(清真食堂),很清真地吃了一顿,然后半睡半醒地去了机房,考试的时候昏昏欲睡(所以就睡了),最后最水的一道题都没做出来,成绩出来之后果然是初中的学弟全场rank1,感到深深的差距和压力,中午回去决心补觉,室友都没睡,吵吵着玩儿手机玩儿电脑,写题,起床之后还是精神萎靡,胡教说到时候讲课的时候,要给他们建议,电脑广播窗口都开小窗,这样你们既可以边学,也可以边听,这样的好处就是如果太简单,你们也可以刷自己的题,我在旁边笑了笑。
下午没在机房,没有电脑,也没有什么小窗教学,东北的气候很好,天气很好,空气很好,阳光很好,从阶梯教室照进来暖洋洋的,正适合(睡觉)学习,内容太难,数学本来就差,根本听不懂莫比乌斯反演和卷积。欧拉函数,积性函数,离散对数这些也是勉强有一些听懂,下课时个别大佬响亮的掌声吵醒了众多睡觉的人,课后胡教说你以后别来了,来了也是睡觉,我心里想着其他一堆睡觉的,我只睡了不到半个小时,很伤心,可能是自己不争气吧,毕竟太弱了,qq因为异地登陆被冻结,我失去很多联系,着实难过,感觉是被世界遗弃的弱者
好吧,吐槽也吐槽了,写题解吧
看到这篇博客的肯定会觉得这啥水题,这么垃圾(我能说什么,t3对我来说很难啊,我到现在不会tarjan缩点)
首先看t1,用map存一下就行了,建一个int->int的map,每有新元素就m[i]++,然后打擂台找最大就行,几行代码就解决了,其实也就是存很多次上升序列,最多有多少就要存多少个,比如
1 4 2 3 8 6 0 9 9 6 4
会在
0 1 2 3 4 6 8 9 4 6 9
的时候收益最大
所以我们可以这样看
(0 1 2 3 4 6 8 9)(4 6 9)
因为后面括号里的数放到前面去是对答案没有贡献的,故这样是一种最优的方式,如果有三个重复的,比如
(0 1 2 3 4 5 6 7 8 9)(4 5 6)(4 5)
故只需要找到出现次数最多的数出现的次数即可
1A代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
using namespace std;
map<int,int>m;
int n,temp,maxn;
int main(){
scanf("%d",&n);
for(register int i=1;i<=n;i++){
scanf("%d",&temp);m[temp]++;
maxn=max(maxn,m[temp]);
}
printf("%d",n-maxn);
return 0;
}
接着来看t4,这道题只需要保存pos,然后贪就行了,我都不好意思讲,大概是这么个意思
对于A到B这种情况,也就是pos处于L和R之间的,就continue,如果L大于pos,就加L-pos,更新pos,如果R小于pos,就加pos-R,更新pos
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,m,l,r,nowl,nowr,cnt,pos;
int main(){
scanf("%d%d",&n,&m);
scanf("%d%d",&l,&r);pos=l;
for(register int i=1;i<=n-1;i++){
scanf("%d%d",&nowl,&nowr);
if(nowl>pos){
cnt+=nowl-pos;
pos=nowl;
}else if(nowr<pos){
cnt+=pos-nowr;
pos=nowr;
}else{
continue;
}
}
printf("%d",cnt);
return 0;
}
Microsoft Edge自动保存了我的线上草稿???我又不小心关了浏览器竟然没掉???
让我们来看第二题(这也是我目前能解决的最后一题了)
回忆一遍题,是叫我们求[a,b]的区间异或(XOR)上一个数的异或和。
F.自然可以想到转化为求[1,b]的异或和减去[1,a-1]的异或和
S.画一个表(t是ten,为了工整)
__t 9 8 7 6 5 4 3 2 1
1 0 0 0 0 0 0 0 0 0 1
2 0 0 0 0 0 0 0 0 1 0
3 0 0 0 0 0 0 0 0 1 1
4 0 0 0 0 0 0 0 1 0 0
5 0 0 0 0 0 0 0 1 0 1
6 0 0 0 0 0 0 0 1 1 0
7 0 0 0 0 0 0 0 1 1 1
8 0 0 0 0 0 0 1 0 0 0
9 0 0 0 0 0 0 1 0 0 1
t 0 0 0 0 0 0 1 0 1 0
可以发现如下几条规律
首先,每一列的前导0的个数在列数为i时为2^(i-1)-1
然后,对于第i列,循环为2^i,其中每个循环有2^(i-1)个1,也有相同数量的0,比如第一列的循环节为10,第二列为1100,我们规定循环节从1开始,因为求出前导零后将删去前导零的个数
所以我们要做的,就是计算出1到b的每一列的0个数和1个数,计算出1到a-1的0个数和1个数,然后a到b的零个数应该为1到b的零个数减去1到a-1的零个数,a到b的1个数求法相同,求出a到b的0和1的个数后,再把c用二进制表示出来,如果c的第i位为0的话,那么该位对答案的贡献为a到b的第i位的1的个数乘以该位的意义(意义是指二进制101中左边的1表示4,右边的表示1,也就是2^(i-1))
结果记得取模
#include<cstdio>
#include<iostream>
#include<cstring>
#include<map>
#define idy 23333333333333333
using namespace std;
int T;
long long a,b,c;
long long cnt_1_b[64][2],cnt_1_a[64][2],cnt[64][2],cs[64];
map<long long,int>m;
long long final;
int maxb,maxa,maxn,maxc;
long long lowbit(long long x){return x&-x;}
void init(){
memset(cnt,0,sizeof(cnt));
memset(cnt_1_a,0,sizeof(cnt_1_a));
memset(cnt_1_b,0,sizeof(cnt_1_b));
maxb=-1;
maxn=-1;
long long te=1;
int mp=1;
while((te<<1)<=b)mp++,te<<=1;
maxb=max(maxb,mp);
maxn=max(maxn,maxb);
for(int i=1;i<=maxb;i++){
long long tt=(1<<(i-1))-1;
te=(b-tt)/(1<<i);
cnt_1_b[i][0]+=tt;
cnt_1_b[i][1]+=te*(1<<(i-1));
cnt_1_b[i][0]+=te*(1<<(i-1));
long long mp=(b-tt)%(1<<i);
if(mp<=(1<<(i-1))) cnt_1_b[i][1]+=mp;
else{
cnt_1_b[i][1]+=(1<<(i-1));
cnt_1_b[i][0]+=(mp-(1<<(i-1)));
}
}
mp=1,te=1;
while((te<<1)<=a)mp++,te<<=1;
maxa=-1;
maxa=max(maxa,mp);
maxn=max(maxn,maxa);
for(int i=1;i<=maxa;i++){
long long tt=(1<<(i-1))-1;
te=(a-tt)/(1<<i);
cnt_1_a[i][0]+=tt;
cnt_1_a[i][1]+=te*(1<<(i-1));
cnt_1_a[i][0]+=te*(1<<(i-1));
long long mp=(a-tt)%(1<<i);
if(mp<=(1<<(i-1))) cnt_1_a[i][1]+=mp;
else{
cnt_1_a[i][1]+=(1<<(i-1));
cnt_1_a[i][0]+=(mp-(1<<(i-1)));
}
}
for(int i=maxa+1;i<=maxb;i++){
cnt_1_a[i][0]=a;
}
for(int i=1;i<=maxn;i++){
cnt[i][1]=cnt_1_b[i][1]-cnt_1_a[i][1];
cnt[i][0]=cnt_1_b[i][0]-cnt_1_a[i][0];
}
}
void solve(){
memset(cs,0,sizeof(cs));
int te,mp;
te=c;
while(te){
mp=lowbit(te);
cs[m[mp]]=1;
te-=mp;
}
final=0;
mp=1,te=1;
while((te<<1)<=c)mp++,te<<=1;
maxc=-1;
maxc=max(maxc,mp);
maxn=max(maxn,maxc);
if(maxc>maxb){
for(int i=maxb+1;i<=maxc;i++){
cnt[i][0]+=b-a;
}
}
for(int i=1;i<=maxn;i++){
if(cs[i]==0){
final=(final+((1<<(i-1))*cnt[i][1]))%idy;
}else{
final=(final+((1<<(i-1))*cnt[i][0]))%idy;
}
}
printf("%lld\n",final);
}
int main(){
long long temp=1;m[temp]=1;
for(long long i=1;i<=62;i++){
m[temp*2]=i+1;
temp*=2;
int te=m[temp];
}
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&a,&b,&c);a=a-1;
init();
solve();
}
return 0;
}
最后一道题等我会了再回来填坑吧,回寝室洗澡了,再吐槽一句,学校里没有超市,买东西还得打电话给外面的超市,结果要买的东西都没有,伤心…