[小菜一碟]4.11测试讲解

#0.0 前言

这里是本人出的校内测试题水题的题解,题面见此:【氵题】,Password:0411
(T3 不是我出的,所以我不写 T3 题解(-、-))

#1.0 悠闲的小Aik

#1.1 理解题意

首先,不得不承认,因为本人的语文水平较低,导致题面有些难懂,我们来看几个问题

  1. \(c_i\) 到底是干什么用的?到底是什么意义?

\(c_i\) 可以这么理解:对于关卡 \(i\),若 \(\exists k\in[i-c_i,i-1]\),第 \(k\) 关已被通过,那么可以直接挑战第 \(i\)

  1. 来看下面这个数学式子:

\[p = 7^{362},q=49^{4}\\ M\equiv2\times(p-\left\lfloor\dfrac{p}{100}\right\rfloor\times100 + q-\left\lfloor\dfrac{q}{15}\right\rfloor\times15)(\text{mod }100) \]

其实 \(7^{362}\)\(49^4\) 这两个数是我直接从选修4-6上抄下来的,运用费马小定理易知:

\[p\equiv49(\text{mod }100),q\equiv1(\text{mod }15) \]

故有

\[M\equiv2\times50\equiv0(\text{mod }100) \]

由此我们知道了,在任意时刻,\(M\) 总能被 \(100\) 整除,再结合数据范围 \(M\leq10^4\),可以看出,\(M\) 的实际取值只有 \(101\) 个数(\(0\times100\sim100\times100\)

#1.2 设计状态,写出方程

我们可以这样设计状态:

\(f_{i,j}\) 表示到达第 \(i\) 关时能力值为 \(j\),在该状态下通过这一关后的最小步数

显然有转移方程:

\[f_{i,j}=\min\limits_{i-c_i\leq k< i}\{f_{k,j-b_k}\}+1. \]

来理解一下上面的柿子,我们的转移候选区间为 \([i-c_i,i-1]\),我们需要一个最小的 \(f_{k,j-b_k}\),在此基础上进行转移,即步数加一。那么为什么是 \(j-b_k\)?回想我们刚才设计的状态:第二维的 \(j\) 是到达时的能力值而非通过后,所以我们需要减去上一关的收益。因为在任意时刻 \(M\) 都可以被 \(100\) 整除,所以我们直接在输入后处理即可。

#1.3 伪代码

\(j\) 的范围很小,可以直接枚举,时间复杂度 \(O(100\cdot n^2)\)

\[\begin{aligned} &\text{set}(f,\infty)\\ &\text{For }i\leftarrow1\text{ to }n\text{ do}\\ &\quad\quad \text{For }j\leftarrow a_i\text{ to }100\text{ do}\\ &\quad\quad\quad\quad \text{For }k\leftarrow i-c_i\text{ to }i-1\text{ do}\\ &\quad\quad\quad\quad\quad\quad f_{i.j}\leftarrow\min\{f_{i,j},f_{k,j-b_k}\}\\ &\quad\quad\quad\quad f_{i,j}\leftarrow f_{i,j}+1\\ \end{aligned} \]

#1.4 优化

很显然,上面程序的时间复杂度使我们不能接受的,考虑优化。

观察上面的状态转移方程:

\[f_{i,j}=\min\limits_{i-c_i\leq k< i}\{f_{k,j-b_k}\}+1. \]

我们想要的仅是区间 \([i-c_i,i-1]\) 的最小值,当 \(i\) 变为 \(i+1\) 时,方程变为:

\[f_{i+1,j}=\min\limits_{i+1-c_{i+1}\leq k< i+1}\{f_{k,j-b_k}\}+1. \]

题干中又给出 “\(c_i\) 非严格递减”,这也就意味着,对于同一个 \(j\) 时,\(f_{i,j}\)\(f_{i+1,j}\) 的候选区间有很大的交叉,区间左端点会向右平移几位,右端点向右平移一位。这样的特点不能不让我们想起 单调队列,但要是 \(j\) 变化呢?

\[f_{i,j+1}=\min\limits_{i-c_i\leq k< i}\{f_{k,j+1-b_k}\}+1. \]

候选区间已经完全不一样了,但是,\(j\) 的范围很小,我们为什么不能多开几个单调队列?于是,我们可以对于每一个 \(j\),单独看一个单调队列。

几个注意的点:

  • 由于我们设计的状态,在更新完 \(f_{i,j}\) 后,我们应当将其加入 \(j'=j+b_i\) 的候选区间,也就是 \(j+b_i\) 这条单调队列
  • 在维护单调性时,我们应将 \(f_{i,j}\) 与队列尾部的 \(f_{k,j+b_i-b_k}\) 进行比较,请结合上一条进行理解。
const int N = 50010;
const int INF = 0x3fffffff;

struct Hurdle{
    int a;
    int b;
    int c;
};
Hurdle h[N];

int n,x,f[N][201],q[201][N];
int frt[201],tal[201];

int main(){
    mset(tal,-1); //memset(tal,-1,sizeof(tal));
    mset(f,0x3f);
    scanf("%d%d",&n,&x);
    x /= 100;
    for (int i = 1;i <= n;i ++){
    	int a,b,c;
    	scanf("%d%d%d",&a,&b,&c);
    	h[i].a = a / 100;
    	h[i].b = b / 100;
    	h[i].c = c;
	}
      
    f[1][x] = 1;
    q[h[1].b + x][++ tal[h[1].b + x]] = 1;
    
    for (int i = 2;i <= n;i++){
        for (int j = 100;j >= h[i].a;j --){
        	int nxt = j + h[i].b;
            while (frt[j] <= tal[j] && q[j][frt[j]] < i - h[i].c)
              frt[j] ++;
            if (frt[j] <= tal[j])
              f[i][j] = f[q[j][frt[j]]][j - h[q[j][frt[j]]].b] + 1;
            while (frt[nxt] <= tal[nxt] && f[q[nxt][tal[nxt]]][nxt - h[q[nxt][tal[nxt]]].b] >= f[i][j])
              tal[nxt] --;
            q[nxt][++ tal[nxt]] = i;
        }
    }
    
    int minn = INF;
    for (int i = 0;i <= 100;i ++)
      minn = min(minn,f[n][i]);
    if (minn > n) cout << "+200";
    else cout << minn;
    return 0;
}

#2.0 卡牌大师

#2.1 简化题目

至多 \(m\)\(A\) 与至多 \(n\)\(B\) 可形成的排列总数(不计空排列)

#2.2 颓柿子

依次考虑 \(A\) 的个数与 \(B\) 的个数,可知答案为

\[\sum\limits_{i=0}^m\sum\limits_{j=0}^n\dbinom{i+j}{i}-1 \]

直接循环处理这个柿子的时间复杂度为 \(O(mn)\),显然不行,要颓柿子

我们知道,有 朱世杰恒等式[1]

\[\sum\limits_{i=0}^n\dbinom{i+m}{m}=\dbinom{n+m+1}{m+1} \]

我们的柿子正好符合这个形式

\[\begin{aligned} &\sum\limits_{i=0}^m\sum\limits_{j=0}^n\dbinom{i+j}{i}-1\\ =&\sum\limits_{i=0}^m\dbinom{i+n+1}{i+1}-1\\ =&\sum\limits_{i=1}^{m+1}\dbinom{i+n}{i}-1=\sum\limits_{i=1}^{m+1}\dbinom{i+n}{i}-1\\ =&\sum\limits_{i=0}^{m+1}\dbinom{i+n}{i}-\dbinom{n}{0}-1=\sum\limits_{i=0}^{m+1}\dbinom{i+n}{n}-2\\ =&\dbinom{n+m+1+1}{n+1}-2=\dbinom{n+m+2}{n+1}-2 \end{aligned} \]

好的,现在我们得到了一个看似简单了许多的柿子,但是注意到 \(n,m\leq10^{18}\),虽然有模数 \(19260817\),但仍旧无法得到我们想要的结果,如果要预处理,\(n,m\) 太大了,如果要直接用 \(\tbinom{n}{m}=\tfrac{n!}{m!(n-m)!}\),显然 \(n,m\) 依旧太大,所以要使用另一个定理:Lucas 定理[2]

\(p\) 是一个质数,\(n\)\(p\) 进制表示为 \(a_0+a_1p^1+a_2p^2+\cdots+a_kp^k\)\(m\)\(p\) 进制表示为 \(b_0+b_1p^1+b_2p^2+\cdots+b_kp^k\),那么有:

\[\dbinom{n}{m}\equiv\prod\limits_{i=0}^k\dbinom{a_i}{b_i}(\text{mod }p). \]

所以,我们就可以将 \(n+m+2\)\(n+1\) 分别转为 \(p\) 进制,再运用卢卡斯定理即可。

我们再次注意到,如果要递推求 \(\tbinom{a_i}{b_i}\),最大要预处理到 \(\tbinom{p}{p}\),时间、空间复杂度都为 \(O(p^2)\),不能接受,所以我们可以线性求阶乘以及其逆元,然后直接使用 \(\tbinom{n}{m}=\tfrac{n!}{m!(n-m)!}\) 即可。

const int N = 20000010;
const int MOD = 19260817;
const int INF = 0x3fffffff;

ll t,k,n,m,tms[N],inv[N],tmsinv[N],ans,coe[2][3];
ll p[3] = {1,19260817,370979071507489};

inline void pre_c(){
    tms[0] = 1,tmsinv[0] = 1,inv[1] = tmsinv[1] = 1;
    for (int i = 1;i < N;i ++)
      tms[i] = (tms[i - 1] * i) % MOD;
    for(int i = 2;i <= MOD;i ++){
        inv[i] = (MOD - MOD / i) * inv[MOD % i] % MOD;
        tmsinv[i] = tmsinv[i - 1] * inv[i] % MOD;
    }
}

inline ll C(ll i,ll j){
    if (i < j) return 0;
    if (j == 0) return 1;
    return ((tms[i] * tmsinv[j]) % MOD) * tmsinv[i - j] % MOD;
}

inline void get_coe(ll x,int rel){
    int last = 2;
    while (x > 0){
        while (x < p[last])
          last --;
        coe[rel][last] = x / p[last];
        x -= coe[rel][last] * p[last];
    }
}

int main(){
    pre_c();
    scanf("%lld",&t);
    while (t --){
        scanf("%lld%lld",&n,&m);
        ans = 1;
        mset(coe,0);
        get_coe(m + n + 2,0);
        get_coe(m + 1,1);
        for (int i = 0;i <= 2;i ++)
          ans = (ans * C(coe[0][i],coe[1][i])) % MOD;
        printf("%lld\n",((ans - 2) % MOD + MOD) % MOD);
    }
    return 0;
}

#3.0 补充证明

#3.1 朱世杰恒等式

考虑 \((x+1)^{n+m+1}\) 中项 \(x^{m+1}\) 的系数.

\[(x+1)^{n+m+1}=\begin{matrix}\underbrace{(x+1)(x+1)\cdots(x+1)}\\n+m+1个\end{matrix}\\ \]

柿子左边的项 \(x^{m+1}\) 的系数显然是 \(\tbinom{n+m+1}{m+1}\),再来看右边。

我们考虑对第一个 \(x\) 选取的位置进行分类,第一个 \(x\) 最小在第一个柿子里取,最大在第 \(n+1\) 个柿子里取,剩下 \(m\)\(x\) 在其后面的几项中取,故其系数应为:

\[\begin{aligned} &\sum\limits_{i=1}^{n+1}\dbinom{n+m+1-i}{m}=\sum\limits_{i=0}^{n}\dbinom{n+m-i}{m}\\ =&\sum\limits_{i=0}^{n}\dbinom{m+(n-i)}{m}=\sum\limits_{i=0}^{n}\dbinom{m+i}{m}\\ \end{aligned} \]

那么,等式两边 \(x^{m+1}\)的系数应当是相等的,所以有

\[\sum\limits_{i=0}^n\dbinom{i+m}{m}=\dbinom{n+m+1}{m+1}\tag{1} \]

证毕.

#3.2 Lucas 定理

易知,当 \(1\leq j \leq p^i-1,i\geq1\) 时,\(\tbinom{p^i}{j}\)\(p\) 的倍数,故

\[(1+x)^{p^i}=1+x^{p^i}+\sum\limits_{j=1}^{p^i-1}\dbinom{p^i}{j}x^j\equiv1+x^{p^i}(\text{mod }p). \]

所以有

\[\begin{aligned} (1+x)^n=&(1+x)^{\sum\limits_{i=0}^ka_ip^i}=\prod\limits_{i=0}^k[(1+x)^{p^i}]^{a_i}\equiv\prod\limits_{i=0}^k(1+x^{p^i})^{a_i}\\ =&\prod\limits_{i=0}^k\left[\sum\limits_{j_i=0}^{a_i}x^{j_ip^i}\dbinom{a_i}{j_i}\right] \end{aligned} \]

上式左端 \(x^m\) 的系数为 \(\tbinom{n}{m}\),考虑到 \(m\) 表示成 \(p\) 进制的唯一性,\(m=b_0+b_1p^1+\cdots+b_kp^k\),故上式右端 \(x^m\) 的系数应为

\[\prod\limits_{i=0}^k\dbinom{a_i}{b_i}(\text{mod }p). \]

故有

\[\begin{equation} \dbinom{n}{m}\equiv\prod\limits_{i=0}^k\dbinom{a_i}{b_i}(\text{mod }p).\tag{2} \end{equation} \]

证毕.

在考后讲解时遇到了这样的问题:

\(b_i\) 有可能大于 \(a_i\),那么此时式 \((2)\) 仍成立吗?

仍成立。

证明:

根据组合数的定义,我们知道,当 \(a_i<b_i\) 时,\(\tbinom{a_i}{b_i}=0\),所以式 \((2)\) 右端的柿子等于零;再来看左边的柿子:

\[\begin{aligned} (1+x)^n=&(1+x)^{\sum\limits_{i=0}^ka_ip^i}=\prod\limits_{i=0}^k[(1+x)^{p^i}]^{a_i}\\ =&\prod\limits_{i=0}^k[1+x^{p^i}+\sum\limits_{j_i=1}^{p^i-1}\dbinom{p^i}{j_i}x^{j_i}]^{a_i} \end{aligned} \]

所以得

\[\begin{align} (1+x)^n=\prod\limits_{i=0}^k[1+x^{p^i}+\sum\limits_{j_i=1}^{p^i-1}\dbinom{p^i}{j_i}x^{j_i}]^{a_i}\tag{3} \end{align} \]

不难发现,在式 \((3)\) 右边出现项 \(x^{b_ip^i}\) 是有可能的,我们将 \([1+x^{p^i}+\sum\limits_{j_i=1}^{p^i-1}\dbinom{p^i}{j_i}x^{j_i}]^{a_i}\) 展开,得到:

\[\begin{matrix}\underbrace{(1+x^{p^i}+\sum\limits_{j_i=1}^{p^i-1}\dbinom{p^i}{j_i}x^{j_i})(1+x^{p^i}+\sum\limits_{j_i=1}^{p^i-1}\dbinom{p^i}{j_i}x^{j_i})\cdots(1+x^{p^i}+\sum\limits_{j_i=1}^{p^i-1}\dbinom{p^i}{j_i}x^{j_i})}\\a_i个\end{matrix} \]

显然有多种选取方法可以得到 \(x^{b_ip^i}\),比如在第一个柿子中选 \(x^{p^i}\),在第二个式子中选 \(x^{b_i}\),其他的柿子都选 \(1\),最终的结果即为 \(x^{b_ip^i}\)。但注意到,无论怎样选取,必然有至少一个因子是从 \(\sum_{j_i=1}^{p^i-1}\tbinom{p^i}{j_i}x^{j_i}\) 中选取得到的,所以项 \(x^{b_ip^i}\) 前的系数至少有一个为 \(\tbinom{p^i}{j_i},1\leq j_i\leq p^i-1\),而我们知道 \(p|\tbinom{p^i}{j_i},1\leq j_i\leq p^i-1\),故上式在模 \(p\) 意义下时,设 \(x^{b_ip^i}\) 的系数为 \(\alpha\),必然有

\[p|\alpha,\quad\alpha x^{b_ip^i}\equiv0(\text{mod }p). \]

所以 \(x^{b_ip^i}\) 的系数在模 \(p\) 意义下为 \(0.\)

那么,在由相乘得到 \(x^m=x^{b_0+b_1p^1+\cdots+b_kp^k}\) 时,自然项 \(x^m\) 的系数也为 \(0\),所以,式 \((3)\) 左边项 \(x^m\) 的系数在模 \(p\) 意义下为 \(0\),而单独分析式 \((3)\) 左端柿子中 \(x^m\) 的系数应为 \(\tbinom{n}{m}\),所以可知

\[\dbinom{n}{m}\equiv0\equiv\prod\limits_{i=0}^k\dbinom{a_i}{b_i}(\text{mod }p). \]

即得式 \((2)\)\(\exists a_i<b_i\) 时仍成立。

证毕.
posted @ 2021-04-12 11:04  Dfkuaid  阅读(85)  评论(2编辑  收藏  举报