NOIP 模擬 $21\; \rm Median$
阿新 • • 發佈:2021-07-21
題解
題解 \(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();}