• 洛谷 NOIP 2023 模拟赛 挑战 NPC IV


    洛谷 NOIP 2023 模拟赛 挑战 NPC IV

    题目大意

    设 f ( x ) = 1 + log ⁡ 2 lowbit ( x ) f(x)=1+\log_2\text{lowbit}(x) f(x)=1+log2​lowbit(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∑n​r=l∑n​i=l∑r​f(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∑n​r=l∑n​i=l∑r​f(pi​)=i=1∑n​f(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的情况的启发下,我们发现:

    • 若 p i p_i pi​和 p j p_j pj​的最低位 1 1 1的位置相同,则交换 p i p_i pi​和 p j p_j pj​不会改变权值
    • 交换 p i p_i pi​和 p n − i + 1 p_{n-i+1} pn−i+1​也不会改变权值

    我们推测:权值取到最小值的排列有很多。

    事实上,当 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))。

    code

    #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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
  • 相关阅读:
    【语音识别】在Win11使用Docker部署FunASR服务器
    时序预测 | MATLAB实现CNN-GRU卷积门控循环单元时间序列预测(风电功率预测)
    【夜读】影响一生的五大定律内心强大的人,有这五种特质
    (二) selenium元素定位
    苹果宣布9月26日发布全新macOS Sonoma系统 新增不少实用功能
    wpfui:一个开源免费具有现代化设计趋势的WPF控件库
    排名前五的设备管理软件
    初见物理引擎库Cannon.js(2)
    损失函数总结
    系统安全分析与设计
  • 原文地址:https://blog.csdn.net/tanjunming2020/article/details/134428466