• XJOI1105模拟赛 积木游戏


    orz duck!

    Description

    在一个 (n)(m) 列的矩阵里放积木。要求:一块积木只能放在一行,一行中相邻的积木中间至少有一个间隔,第一行至少有一块积木,第 (n) 行积木长度为 (m)。求所有满足条件的方案的积木数平方和

    Solution

    注意到原题范围 (n,mleq 5 imes 10^3) 太小了,考虑加强 ( ightarrow~n,mleq 10^{18})

    首先把这个第一行至少有一块积木的限制去掉,记 (f_n) 表示最高积木高度小于等于 (n) 的积木数平方和,则答案即为 (f_n - f_{n-1})

    对于一个积木的高度序列 ({a_m}),很容易求出它有多少块积木,即 (summax{a_i-a_{i-1},0})。注意到显然去掉这个约束以后,对于每种积木的高度序列是等概率出现的,考虑把数数转化为概率,最后乘上一个总方案数即可,具体地:

    [f_n = n^moperatorname Eleft(left(summax{a_i-a_{i-1},0} ight)^2 ight) ]

    把那个 (max) 拆开,得到:

    [f_n = n^moperatorname Eleft(sum_isum_jmax{a_i-a_{i-1},0}max{a_j-a_{j-1},0} ight) ]

    然后分类讨论 (i,j) 的情况,分 (i=j)(|i-j|=1)(|i-j|>1) 讨论,其中 (i=1)(j=1) 还要进一步讨论。

    注意到每种情况都是一个关于 (n) 的低次多项式,可以使用拉格朗日插值减少计算。

    Code

    (整数类模板省略)

    const int MOD = 998244353;
    
    inline Z suan1(Z N) { return N * 166374059 + N * N * 499122177 + (N ^ 3) * 332748118; }
    inline Z suan2(Z N) { return N * N * 415935147 + (N ^ 4) * 582309206; }
    inline Z suan3(Z N) { return N * 415935147 + N * N * 707089750 + (N ^ 3) * 582309206 + (N ^ 4) * 291154603; }
    inline Z suan4(Z N) { return N * N * 415935147 + (N ^ 3) * 415935147 + (N ^ 4) * 582309206 + (N ^ 5) * 582309206; }
    inline Z suan5(Z N) { return N * 432572553 + (N ^ 3) * 707089750 + (N ^ 5) * 856826403; }
    inline Z suan6(Z N) { return N * N * 859599304 + (N ^ 4) * 277290098 + (N ^ 6) * 859599304; }
    
    int n, m;
    
    inline Z calc(int n, int m) {
    	if (!n) return Z(0);
    	if (n == 1) return Z(1);
    	Z N(n), M(m), ans = suan1(N) / N;
    	if (m > 1) ans += (M - 1) * suan2(N) / (N * N);
    	if (m > 1) ans += 2 * suan3(N) / (N * N);
    	if (m > 2) ans += 2 * (M - 2) * suan4(N) / (N ^ 3);
    	if (m > 2) ans += 2 * (M - 2) * suan5(N) / (N ^ 3);
    	if (m > 3) ans += (M - 2) * (M - 3) * suan6(N) / (N ^ 4);
    	return ans;
    }
    
    int main() {
    	scanf("%d%d", &m, &n);
    	Z ans = calc(n, m) * (Z(n) ^ m) - calc(n - 1, m) * (Z(n - 1) ^ m);
    	printf("%d
    ", ans.x);
    	return 0;
    }
    

    事实上如果真的要做 (n,mleq 10^{18}) 这份代码还要作亿点改动(因为大于模数了)但是由于懒就不想管了

  • 相关阅读:
    【node.js】GET/POST请求、Web 模块
    【node.js】全局变量、常用工具、文件系统
    【node.js】函数、路由
    【node.js】模块系统、函数
    【node.js】Stream(流)
    跨域问题的产生,怎么解决它?
    array.splice()
    数组的方法
    js跨域请求的5中解决方式
    3分钟看懂flex布局
  • 原文地址:https://www.cnblogs.com/realSpongeBob/p/XJOI20201105-bricks.html
Copyright © 2020-2023  润新知