NOIP 模拟 $21\; \rm Median$
题解 \(by\;zj\varphi\)
对于这个序列,可以近似得把它看成随机的,而对于随机数列,每个数的分布都是均匀的,所以中位数的变化可以看作是常数
那么可以维护一个指向中位数的指针,同时维护有多少个小于等于它的数。
让这个指针跳值域,用有多少个小于等于它的数来判断
对于 \(k\) 为偶数的情况,维护两个指针即可
注意:素数要卡着筛,而且用 \(bitset\) 必须开 \(O2\)
Code
#include<bits/stdc++.h>
#define ri register signed
#define p(i) ++i
using namespace std;
namespace IO{
char buf[1<<21],*p1=buf,*p2=buf;
#define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++
template<typename T>inline void read(T &x) {
ri f=1;x=0;register char ch=gc();
while(ch<'0'||ch>'9') {if (ch=='-') f=0;ch=gc();}
while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
x=f?x:-x;
}
}
using IO::read;
namespace nanfeng{
#define FI FILE *IN
#define FO FILE *OUT
template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
typedef long long ll;
static const int N=1.8e8+7,M=1e7+7;
int prim[M],s[M],s2[M],T[M<<1],lw,lw1,cnt,n,k,w,sum,mid,mid1,hk;
ll ans;
bitset<N> vis;
void Getprime() {
ri n=N-7;
for (ri i(2);i<=n;p(i)) {
if (!vis[i]) vis[prim[p(cnt)]=i]=1;
for (ri j(1);j<=cnt&&prim[j]*i<=n;p(j)) {
vis[i*prim[j]]=1;
if (!(i%prim[j])) break;
}
}
}
inline void mv1() {
while(lw<=hk) {
lw+=T[p(mid)];
if (lw>hk) break;
}
while(lw-T[mid]>hk) lw-=T[mid--];
}
inline void mv2() {
while(lw<=hk-1) {
lw+=T[p(mid)];
if (lw>=hk) break;
}
while(lw-T[mid]>=hk) lw-=T[mid--];
while(lw1<=hk) {
lw1+=T[p(mid1)];
if (lw1>hk) break;
}
while(lw1-T[mid1]>hk) lw1-=T[mid1--];
}
inline int main() {
// FI=freopen("nanfeng.in","r",stdin);
// FO=freopen("nanfeng.out","w",stdout);
Getprime();
read(n),read(k),read(w);
hk=k>>1;
for (ri i(1);i<=n;p(i)) s[i]=(ll)prim[i]*i%w;
for (ri i(1);i<=n;p(i)) s2[i]=s[i]+s[i/10+1];
if (k&1) {
for (ri i(1);i<=n;p(i)) {
p(T[s2[i]]);
if (i>k&&s2[i]<=mid) p(lw);
if (i>=k) {
mv1(),ans+=mid;
if (s2[i-k+1]<=mid) --lw;
--T[s2[i-k+1]];
}
}
} else {
for (ri i(1);i<=n;p(i)) {
p(T[s2[i]]);
if (i>k&&s2[i]<=mid) p(lw);
if (i>k&&s2[i]<=mid1) p(lw1);
if (i>=k) {
mv2(),ans+=mid+mid1>>1;
if ((mid+mid1)&1) p(sum);
if (s2[i-k+1]<=mid) --lw;
if (s2[i-k+1]<=mid1) --lw1;
--T[s2[i-k+1]];
}
}
}
ans+=sum>>1;
printf("%lld",ans);
if (sum&1) puts(".5");
else puts(".0");
return 0;
}
}
int main() {return nanfeng::main();}