對每個數,先分類討論,將答案分為這個數有翻倍和這個數沒翻倍。
在討論前,我們規定:\(low(x)\)為小於等於這個數的數的個數,當前數為\(x\)。
如果這個數沒翻倍:我們考慮哪些數翻倍不會影響這個數的排名,一種是翻倍後依然小於\(x\)的,一種是本來就大於等於\(x\)的。
那麼對於第一種情況,情況數為
\[c(low((x+1)/2-1)+n-low(x-1)-1,k)
\](\(c(n,m)\)為組合數,下同)
這裡前面一項最後的減一表示不能選當前數。
如果這個數翻倍了:我們考慮那些數必須翻倍,那些數可以選擇性翻倍。
必須翻倍的數就是為了維持原排名所需翻倍的數,就是小於\(2x\)同時大於等於\(x\)的所有數。
選擇翻倍的數就是翻倍後不會影響當前排名的數,就是小於\(x\)的數和大於等於\(2x\)的數的數。
這裡要注意,如果必須翻倍的數大於\(k\)那麼在這種討論中就不可能有情況滿足當前數排名不變。
設必須翻倍的數為\(js=low(2x-1)-low(x-1)\),那麼對於第二種情況,情況數為
\[c(n-js,k-js)
\]那麼答案就是兩者相加了。
#includeusing namespace std;
const int n=100010,p=998244353;
int add(int x,int y)
int mul(int x,int y)
int n,k;
int a[n],b[n];
int fac[n],inv[n];
int c(int n,int m)
int mpow(int a,int n)
return ret;
}int low(int x)
int main()
sort(b+1,b+n+1);
b[0]=-1e9+7;
b[n+1]=0x7fffffff;
for(int i=1;i<=n;++i)
int ret=c(low((a[i]+1)/2-1)+n-low(a[i]-1)-1,k);
int js=low(2*a[i]-1)-low(a[i]-1);
if(k>=js)
printf("%d\n",ret);
}}
PKUSC 2018 真實排名
戳我 我們將現在所要進行的數設為 now 我們分情況討論一下 他自己不翻倍 他自己翻倍 我們首先來看看 1 操作 如果要滿足他對排名沒有影響,那麼不能進行翻倍的數只有 lceil frac rceil,now 我考場上不知道在幹嗎,寫的是能進行翻倍的數,麻煩好多,常數也大 我們假設這一段為 cnt ...
PKUSC2018 真實排名 線段樹 組合數
pkusc2018 真實排名 對於每個數 val 分兩種情況討論 1 當 val 不翻倍時,那麼可以翻倍的是權值比 frac 小的和大於等於 val 的。2 當 val 翻倍時,顯然權值在 val,val 2 1 的都要翻倍,剩下可以翻倍的是權值比 val 小的和大於等於 2 val 的。用權值線段...
P5368 PKUSC2018 真實排名
problem link 對於每個 a i 我們可以考慮這 k 個選手中要不要有 a i 如果沒有的話,那我們就看看有哪些 a j 在翻倍後不會影響到 a i 的排名 顯然 2 a j或者 a i le a j 的這些 a j 都滿足要求,我們記它們的個數為 cnt 1 那麼如果這 k 個中有 a ...