题解:CF2072F Goodbye, Banker Life

前言:怎么说呢,这道题说简单也不简单,说难也不难,简单到找规律也可以写出来,难到不想找规律几乎想不出来……

题目简化:没什么好简化的,题目已经说的很清楚了,就是求一个表的第 nnn 行的数字,这个表满足下列条件:

  • iii 行包含 iii 个整数。

  • 第一行唯一的整数是 kkk

  • 设第 iii 行第 jjj 列的数为 Ti,jT_{i,j}Ti,j,则:

Ti,j={Ti−1,j−1⊕Ti−1,j1<j<iTi−1,jj=1Ti−1,j−1j=iT_{i,j}=\begin{cases}T_{i-1,j-1}\oplus T_{i-1,j}&1\lt j\lt i\\T_{i-1,j}&j=1\\T_{i-1,j-1}&j=i\end{cases}Ti,j=Ti1,j1Ti1,jTi1,jTi1,j11<j<ij=1j=i

突然发现讲着讲着好像复述了一遍题目。

看到这道题,我首先得想法就是找规律。请看这张图:

这里是我列了 121212 行后的图,不难发现:每一行都是对称的,但规律并不是很明显,你们也可以尝试着自己多列几个看看能不能找出规律。

因此,我们就不得不采取第二种方法:算正解。我是这样想的。

因为题目中有异或,而跟异或相关的有一个东西:加法。只不过它是没有进位的加法。这里又有个图表,所以我立马想到了杨辉三角。所以我先对这个图的每一个点都除以一个 kkk,这样就成了一个 01 序列,更方便我们理解后面的东西。

然后我们就可以把杨辉三角带进去了,杨辉三角满足 fi,j=fi−1,j−1+fi−1,jf_{i,j}=f_{i-1,j-1}+f_{i-1,j}fi,j=fi1,j1+fi1,j,跟题目中的一个条件很像,正好也能说明这个思路大概率是对的。但整个图表只有 0 和 1,没有其他的数,这咋办呢?

这也很简单:对杨辉三角的每个数  mod 2\bmod2mod2 就行了。事实证明这样做也能得到原来的 01 序列。

我们又知道杨辉三角的每一项为 Cj−1i−1C_{j-1}^{i-1}Cj1i1,带入可得第 iii 行第 jjj 列的数是:

fi,j=Cj−1i−1 mod 2f_{i,j}=C_{j-1}^{i-1}\bmod2fi,j=Cj1i1mod2

又根据 Lucas 定理(Cnm mod p=C⌊np⌋⌊mp⌋×Cn mod pm mod p mod pC_n^m\bmod p=C_{\lfloor\frac{n}{p}\rfloor}^{\lfloor\frac{m}{p}\rfloor}\times C_{n\bmod p}^{m\bmod p}\bmod pCnmmodp=Cpnpm×Cnmodpmmodpmodp)可知:

fi,j=Cj−12i−12×C(j−1) mod 2(i−1) mod 2 mod 2f_{i,j}=C_{\frac{j-1}{2}}^{\frac{i-1}{2}}\times C_{(j-1)\bmod2}^{(i-1)\bmod2}\bmod2fi,j=C2j12i1×C(j1)mod2(i1)mod2mod2

因为 111 的情况不好算,所以我们来看 000 的情况。

如果上面那个式子是 000,说明两项之积为偶数,但当我们把前面不断拆分之后就会发现只有当 C(j−1) mod 2(i−1) mod 2C_{(j-1)\bmod2}^{(i-1)\bmod2}C(j1)mod2(i1)mod2 为偶数时才成立,而 C(j−1) mod 2(i−1) mod 2C_{(j-1)\bmod2}^{(i-1)\bmod2}C(j1)mod2(i1)mod2 为偶数的情况只有一种:C(j−1) mod 2(i−1) mod 2=0C_{(j-1)\bmod2}^{(i-1)\bmod2}=0C(j1)mod2(i1)mod2=0。由此可知:当 (i−1) mod 2=0(i-1)\bmod2=0(i1)mod2=0(j−1) mod 2=1(j-1)\bmod2=1(j1)mod2=1 时,上述条件才成立(因为没有 C00C_0^0C00 这个东西),这说明 i−1i-1i1j−1j-1j1 在二进制内必然有一位不等,与运算一下就可知,其中 &\&& 表示与运算:

(i−1)&(j−1)≠j−1(i-1)\&(j-1)\not=j-1(i1)&(j1)=j1

那么把上述条件反过来就是等于 111 的情况。

最后把先开始除以的 kkk 乘回去就可以得到:

fi,j=k×[(i−1)&(j−1)=j−1]f_{i,j}=k\times[(i-1)\&(j-1)=j-1]fi,j=k×[(i1)&(j1)=j1]

AC 代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int t,n,k;
signed main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>k;
        for(int i=1;i<=n;i++)
        {
            cout<<(((i-1)&(n-1))==i-1?k:0)<<" ";//带入公式
        }
        cout<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值