洛谷 NOIP 2023 模拟赛 挑战 NPC IV
设 f ( x ) = 1 + log 2 lowbit ( x ) f(x)=1+\log_2\text{lowbit}(x) f(x)=1+log2lowbit(x),对于一个 1 1 1到 n n n的排列 p i p_i pi,其权值为 ∑ l = 1 n ∑ r = l n ∑ i = l r f ( p i ) \sum\limits_{l=1}^n\sum\limits_{r=l}^n\sum\limits_{i=l}^rf(p_i) l=1∑nr=l∑ni=l∑rf(pi)。求一个 1 1 1到 n n n的排列 p i p_i pi,使得这个排列是所有排列中第 k k k小的。输出第 k k k小的权值模 998244353 998244353 998244353后的值。
有 q q q组数据。
测试点编号 | n n n | k ≤ k \leq k≤ | q = q= q= |
---|---|---|---|
1 ∼ 3 1 \sim 3 1∼3 | ≤ 10 \leq 10 ≤10 | n ! n! n! | 2 2 2 |
4 ∼ 8 4 \sim 8 4∼8 | ≤ 1 0 3 \leq 10^3 ≤103 | 2 2 2 | 7 7 7 |
9 ∼ 13 9 \sim 13 9∼13 | ∈ [ 1 0 5 , 1 0 6 ] \in [10^5, 10^6] ∈[105,106] | min ( 1 0 18 , n ! ) \min(10^{18}, n!) min(1018,n!) | 7 7 7 |
14 ∼ 17 14 \sim 17 14∼17 | ≤ 1 0 6 \leq 10^6 ≤106 | min ( 1 0 18 , n ! ) \min(10^{18}, n!) min(1018,n!) | 7 7 7 |
18 ∼ 25 18 \sim 25 18∼25 | ≤ 1 0 18 \leq 10^{18} ≤1018 | min ( 1 0 18 , n ! ) \min(10^{18}, n!) min(1018,n!) | 10 10 10 |
对于 100 % 100\% 100% 的数据,保证 1 ≤ n ≤ 1 0 18 1 \leq n \leq 10^{18} 1≤n≤1018, 1 ≤ k ≤ min ( 1 0 18 , n ! ) 1 \leq k \leq \min(10^{18}, n!) 1≤k≤min(1018,n!), 1 ≤ q ≤ 10 1 \leq q\le 10 1≤q≤10。
时间限制为 max ( q × 0.5 , 2 ) s \max(q\times 0.5, 2)s max(q×0.5,2)s,空间限制为 512 M B 512MB 512MB。
首先,我们可以得出, ∑ l = 1 n ∑ r = l n ∑ i = l r f ( p i ) = ∑ i = 1 n f ( p i ) × i × ( n − i + 1 ) \sum\limits_{l=1}^n\sum\limits_{r=l}^n\sum\limits_{i=l}^rf(p_i)=\sum\limits_{i=1}^nf(p_i)\times i\times (n-i+1) l=1∑nr=l∑ni=l∑rf(pi)=i=1∑nf(pi)×i×(n−i+1)。记 c i = i × ( n − i + 1 ) c_i=i\times (n-i+1) ci=i×(n−i+1), d i = f ( p i ) d_i=f(p_i) di=f(pi)。
我们先考虑 k = 1 k=1 k=1的情况,也就是要最小化 c i × d i c_i\times d_i ci×di的和,我们用最大的 c c c值来匹配最小的 d d d值,次大的 c c c值来匹配次小的 d d d值,以此类推。
当 k = 2 k=2 k=2时,我们在权值最小的排列 p i p_i pi的基础上,交换 p 1 p_1 p1和 p n p_n pn的位置,权值不变,也就是说 k = 2 k=2 k=2时的答案与 k = 1 k=1 k=1的时的答案相同。
在 k = 2 k=2 k=2的情况的启发下,我们发现:
我们推测:权值取到最小值的排列有很多。
事实上,当 n = 29 n=29 n=29时,这样的排列数量就已经超过了 1 0 18 10^{18} 1018,所以,当 n ≥ 29 n\geq 29 n≥29时,答案与 k k k无关,始终为最小的权值。
如果按上面那样做是 O ( n ) O(n) O(n)的,下面考虑优化。
对于每一种 f f f值,我们需要查询 c c c值从小到大排序后一段区间的和,推式子即可,时间复杂度是 O ( log n ) O(\log n) O(logn)的。
当 n ≤ 28 n\leq 28 n≤28时,我们可以用 D P DP DP来做。
设 f [ a ] [ b ] [ c ] [ d ] [ e ] [ s ] f[a][b][c][d][e][s] f[a][b][c][d][e][s]表示目前已经填了前 i = a + b + c + d + e i=a+b+c+d+e i=a+b+c+d+e个数,其中有 a a a个数的最低位为 1 1 1, b b b个数的最低位为 2 2 2,以此类推,且当前的权值为 s s s。
我们枚举下一个位置的最低位 1 1 1的位置 t t t,那么新状态的权值为 s + c i + 1 × t s+c_{i+1}\times t s+ci+1×t。
我们发现,从最低位 1 1 1的位置为 1 1 1到 5 5 5的数的数量分别为 14 , 7 , 4 , 2 , 1 14,7,4,2,1 14,7,4,2,1,还要算上 0 0 0的情况,最大的权值不会超过 10000 10000 10000,那么总状态数 S S S不超过 15 × 8 × 5 × 3 × 2 × 10000 = 3.6 × 1 0 7 15\times 8\times 5\times 3\times 2\times 10000=3.6\times 10^7 15×8×5×3×2×10000=3.6×107,那么 D P DP DP的时间复杂度为 O ( 5 S ) O(5S) O(5S)。
总时间复杂度为 O ( q ( log n + 5 S ) ) O(q(\log n+5S)) O(q(logn+5S))。
#include
using namespace std;
const int N=30,V=10000;
const long long mod=998244353;
const long long ny2=499122177,ny6=166374059;
int T,c[N+5],w[10];
long long n,k,ans,lst,now,f[15][8][5][3][2][V+5];
long long gt2(long long t){
t%=mod;
return t*(t+1)%mod*ny2%mod;
}
long long gt6(long long t){
t%=mod;
return t*(t+1)%mod*(2*t+1)%mod*ny6%mod;
}
long long gt(long long t){
long long re=(t&1)*(t/2+1)%mod*((n-(t/2+1)+1)%mod)%mod;t/=2;
long long tmp=((n+1)%mod*gt2(t)%mod-gt6(t)+mod)%mod;
re=(re+tmp*2)%mod;
return re;
}
void pt(long long *a,long long *b,int t,int p){
for(int i=0;i<=V;i++){
if(b[i]) a[i+t]+=b[i]*p;
}
}
void gt(long long *a){
for(int i=0;i<=V;i++){
if(k>a[i]) k-=a[i];
else{
printf("%d\n",i);
return;
}
}
}
int main()
{
scanf("%d",&T);
while(T--){
scanf("%lld%lld",&n,&k);
ans=0;
if(n>=29){
lst=now=0;
for(int i=60;i>=1;i--){
now=lst+(n+(1ll<<i-1))/(1ll<<i);
ans=(ans+(gt(now)-gt(lst)+mod)%mod*i%mod)%mod;
lst=now;
}
printf("%lld\n",ans);
continue;
}
for(int i=1;i<=n;i++){
c[i]=i*(n-i+1);
}
for(int i=1;i<=5;i++){
w[i]=(n+(1<<i-1))/(1<<i);
}
memset(f,0,sizeof(f));
f[0][0][0][0][0][0]=1;
for(int v1=0;v1<=w[1];v1++)
for(int v2=0;v2<=w[2];v2++)
for(int v3=0;v3<=w[3];v3++)
for(int v4=0;v4<=w[4];v4++)
for(int v5=0;v5<=w[5];v5++){
int sum=v1+v2+v3+v4+v5;
if(v1<w[1]) pt(f[v1+1][v2][v3][v4][v5],f[v1][v2][v3][v4][v5],c[sum+1]*1,w[1]-v1);
if(v2<w[2]) pt(f[v1][v2+1][v3][v4][v5],f[v1][v2][v3][v4][v5],c[sum+1]*2,w[2]-v2);
if(v3<w[3]) pt(f[v1][v2][v3+1][v4][v5],f[v1][v2][v3][v4][v5],c[sum+1]*3,w[3]-v3);
if(v4<w[4]) pt(f[v1][v2][v3][v4+1][v5],f[v1][v2][v3][v4][v5],c[sum+1]*4,w[4]-v4);
if(v5<w[5]) pt(f[v1][v2][v3][v4][v5+1],f[v1][v2][v3][v4][v5],c[sum+1]*5,w[5]-v5);
}
gt(f[w[1]][w[2]][w[3]][w[4]][w[5]]);
}
return 0;
}