[CSP-S模拟测试]:Median(暴力+模拟)

题目描述

定义两个数列:

$$S=\{S(1),S(2),...,S(n)\}\text{和}S_2\{S_2(1),S_2(2),...,S_2(n)\}$$

$$S(k)=(p_k\times k)\mod w,where\ p_k\ is\ the\ kth\ prime\ number$$

$$S_2(k)=S(k)+S(\left\lfloor\frac{k}{10}\right\rfloor+1)$$

令$M(i,j)$表示$S_2(i)$到$S_2(j)$的中位数(个数为奇数就是中间的数,否则为中间的两个数除以二)。现给定$n,k$,求:

$$\sum \limits_{i=1}^{n-k+1}M(i,i+k-1)$$


输入格式

输入只有一行,为三个正整数$n,k,w$(同题意)。


输出格式

输出只有一行,为所求的答案。如果答案不是整数,使用$.5$表示一半,否则用$.0$


样例

样例输入1:

100 10 10007

样例输出1:

387895.5

样例输入2:

100000 10000 10007

样例输出2:

897586519.5


数据范围与提示

对于$20\%$的数据,$n,k\leqslant 6,000$
对于另外$30\%$的数据,$n,k\leqslant 10,000$
对于另外$20\%$的数据,$w=3$
对于$100\%$的数据,$w\leqslant k\leqslant n\leqslant 10^7$


题解

首先,想说一下我在考试的时候的思路(毕竟对着这道$T1$刚了一个小时……)

$10^7$的数据范围$n\log n$可能差不多,于是我想到了$Splay$……

然后我就打了,还以为$A$了这道题。

然后忽然想到筛素数不能只筛到$10^7$,我们需要$10^7$素数,当场歇逼……

因为我发现要筛到$179424673$……

然后我就打算从$w$入手,推式子,找规律,最后啥也没发现,于是我只筛到了$10^7$,因为我觉得多了会$T$(学校$OJ$太菜)……

然而正解告诉我们,就是要筛到$179424673$……

因为$OJ$太才,于是标程$T$掉了,老师把时限开到了$4s$并重测,那些筛到$179424673$的人(本来都$T$飞了……)都拿到了$70$分,然而我差点跌出了前$10$……

擦干眼泪,笑面未来!!!

于是我们开始讲这道题……

思考一个类似莫队的思路,也类似滑动窗口叭~

维护一个指针指向中位数,挪动窗口时更新位置即可($k$是偶数时维护两个即可)。

总之这是一道卡常题,$\Theta(n\log n)$的做法就别想了,因为它是这样的$\downarrow$

然后我去尝试了正解$\downarrow$

其实我也不知道我到底哪里把常数给写大了,总之别人的是这样的$\downarrow$

时间复杂度:$\Theta(179424673+n)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int n,k,w;
int S1[10000001],S2[10000001];
int prime[10000001],cnt;
int t[10000001];
char vis[179424674];
double ans;
void pre_work()
{
	for(int i=2;i<179424674;i++)
	{
		if(!vis[i])prime[++cnt]=i;
		for(int j=1,x;j<=cnt&&(x=i*prime[j])<179424674;j++)
		{
			vis[x]=1;
			if(!(i%prime[j]))break;
		}
	}
}
int main()
{
	pre_work();
	scanf("%d%d%d",&n,&k,&w);
	for(long long i=1;i<=n;i++)S1[i]=prime[i]*i%w;
	for(int i=1;i<=n;i++)S2[i]=S1[i]+S1[i/10+1];
	for(int i=1;i<k;i++)t[S2[i]]++;
	if(k&1)
	{
		int median=(k>>1)+1;
		int lst=0;
		int hand=-1;
		for(int i=k;i<=n;i++)
		{
			t[S2[i]]++;
			if(S2[i]<=hand)lst++;
			if(i>k)
			{
				t[S2[i-k]]--;
				if(S2[i-k]<=hand)lst--;
			}
			while(lst<median)lst+=t[++hand];
			while(lst>=median+t[hand])lst-=t[hand--];
			ans+=hand;
		}
	}
	else
	{
		int median=(k>>1);
		int lst1=0,lst2=0;
		int hand1=-1,hand2=-1;
		for(int i=k;i<=n;i++)
		{
			t[S2[i]]++;
			if(S2[i]<=hand1)lst1++;
			if(S2[i]<=hand2)lst2++;
			if(i>k)
			{
				t[S2[i-k]]--;
				if(S2[i-k]<=hand1)lst1--;
				if(S2[i-k]<=hand2)lst2--;
			}
			while(lst1<median)lst1+=t[++hand1];
			while(lst2<median+1)lst2+=t[++hand2];
			while(lst1>=median+t[hand1])lst1-=t[hand1--];
			while(lst2>=median+1+t[hand2])lst2-=t[hand2--];
			ans+=(double)(hand1+hand2)/2;
		}
	}
	printf("%.1lf",ans);
	return 0;
}


rp++

原文地址:https://www.cnblogs.com/wzc521/p/11631528.html

时间: 2024-10-31 16:46:28

[CSP-S模拟测试]:Median(暴力+模拟)的相关文章

[CSP-S模拟测试]:666(模拟)

题目描述 不忘初心. 小$\pi$假期在家无聊,打开了某弹幕直播网站. 突然,有一个精彩的镜头. 小$\pi$看到了满屏的$6$,其中,有$666$.也有$666666$.也有$6666666666...$ 小$\pi$也想发个弹幕,他打算发$n$个$6$. 然而当他按下第一个$6$时,键盘上$6$的键坏了. 这时,弹幕框里只有$1$个$6$. 键盘坏了什么的不要紧,先把弹幕发了才是正事. 于是小$\pi$打算用复制粘贴这类操作来生成这$n$个$6$. 具体的说,小$\pi$电脑的操作系统有唯一

[CSP-S模拟测试]:真相(模拟)

题目传送门(内部题106) 输入格式 第一行为一个正整数$T$,表示数据组数. 接下来$T$组数据,每组数据第一行一个正整数$n$表示$OIer$,接下来$n$行,第$i$行表示编号为$i$的人所说的话,格式可以参考题面描述. 输出格式 对每组数据,如果这组数据里的$OIer$们说的话无论如何都会产生矛盾,那么就输出一行一个字符串$inconsistent$,否则输出一行一个字符串$consistent$. 样例 样例输入: 33++$ 33+-$ 31- 样例输出: consistentcon

[CSP-S模拟测试]:Rectangle(模拟+树状数组)

题目描述 平面上有$n$个点,第$i$个点的坐标为$X_i,Y_i$.对于其中的一个非空点集$S$,定义$f(S)$为一个最小矩形,满足:$\bullet$覆盖$S$中所有的点(在边界上也算覆盖):$\bullet$边与坐标轴平行.求所有不同的$f(S)$的面积和对$10^9+7$取模的结果.两个矩形被认为是不同的,当且仅当它们顶点坐标不同. 输入格式 从文件$rectangle.in$中读入数据.第一行一个整数$n$.接下来$n$行,每行两个整数$X_i,Y_i$. 输出格式 输出到文件$re

HDU 4831 Scenic Popularity 暴力模拟

Scenic Popularity Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 340    Accepted Submission(s): 110 Problem Description 临近节日,度度熊们最近计划到室外游玩公园,公园内部包括了很多的旅游景点区和休息区,由于旅游景点很热门,导致景点区和休息区都聚集了很多人.所以度度熊

2018冬令营模拟测试赛(五)

2018冬令营模拟测试赛(五) [Problem A][UOJ#154]列队 试题描述 picks 博士通过实验成功地得到了排列 \(A\),并根据这个回到了正确的过去.他在金星凌日之前顺利地与丘比签订了契约,成为了一名马猴烧酒. picks 博士可以使用魔法召唤很多很多的猴子与他一起战斗,但是当猴子的数目 \(n\) 太大的时候,训练猴子就变成了一个繁重的任务. 历经千辛万苦,猴子们终于学会了按照顺序排成一排.为了进一步训练,picks 博士打算设定一系列的指令,每一条指令 \(i\) 的效果

2018冬令营模拟测试赛(十九)

2018冬令营模拟测试赛(十九) [Problem A]小Y 试题描述 输入 见"试题描述" 输出 见"试题描述" 输入示例 见"试题描述" 输出示例 见"试题描述" 数据规模及约定 见"试题描述" 题解 目前未知. 这题目前就能做到 \(O(n \sqrt{M} \log n)\),其中 \(M\) 是逆序对数,然而会被卡 \(T\):当然这题暴力可以拿到和左边那个算法一样的分数,只要暴力加一个剪枝:当左

noip模拟测试21

T1:折纸 这道写崩我也是没话说…… 模拟就完了,记录每次的折叠点,每次将之前的都扫一遍就完了 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cmath> 5 #include<algorithm> 6 #include<cstdlib> 7 #define ll long long 8 using namespace std; 9 con

[考试反思]0929csp-s模拟测试55:沦陷

菜得过分. 面对T1的大板子不知所措,然后T2的贪心不小心把排序语句删了... T1这种大模板啊...其实我是觉得我能打出来的,然后先用一个小时码了一个2k. 然后做T2想贪心就出来了.十分钟码完T3暴力之后回T1打对拍瞬间爆炸. 于是又重新打了一个2k,WA0.对拍发现. 然后考试就没几分钟了交暴力走了. 不要打完就跑,记得早点对拍改进思路. T1: 的确是挺裸的线段树.离散化或者权值线段树都可以. 但是考场上两个都打出来都死了. 最后用离散化A的. 1 #include<cstdio> 2

[考试反思]1002csp-s模拟测试56:凌乱

放假回来状态回升??(玩够了-但是稍困) T1打的不完全对,但是过掉了.很快的想到了二分吧喇叭啦.. 然后T2也挺快想出来了但是挂细节没发现,考试快结束的时候才发现出锅了. 改了过来是正解,但是出题人无良卡了线段树强制树状数组,T了一个子任务,卡常到飞起. T3暴力没什么问题. 卡常是一种习惯.要注意题目数据范围观察是否卡常. T1: 所有的决策都是一条一次函数. 分两类,斜率正或斜率非负. 如果第二类的直线里有在T=0时符合要求的,那么答案就是0,所以check(0)一下. 如果非负的直线都在