zh ink

Back

题目来源于CF2072FProblem - F - Codeforces 我们需要生成一个魔法三角形的第 nn 行。这个三角形的定义如下:

  1. 第 i行有 i个整数。
  2. 第一行只有一个整数 k。
  3. 对于第 i 行的第 j个元素 Ti,TjT_i,T_j其值由以下规则决定:
    • 如果1<j<i1<j<i,则 Ti,j=Ti1,j1T_{i,j}=T_{i-1,j-1}Ti1,jT_{i-1,j}​(即上一行的第 j−1 和第 j 个元素的异或结果)。
    • 如果 j=1,则Ti,j=Ti1,jT_{i,j}=T_{i-1,j}(即上一行的第一个元素)。
    • 如果 j=i,则 Ti,j=Ti,j1T_{i,j}=T_{i,j-1}(即上一行的最后一个元素)。
当k = 3时:
        3 
       3 3 
      3 0 3 
     3 3 3 3 
     
    3 0 0 0 3 
   3 3 0 0 3 3 
  3 0 3 0 3 0 3 
 3 3 3 3 3 3 3 3 
 
3 0 0 0 0 0 0 0 3
plaintext

方法一:递归#

我们发现三角形在2k2^k 行都全为k,并且是由边长为2的全为k的三角形以及对应边长的0的三角形组合而成。子结构相似,可以递归。

void solve(){
	int n,k;
	cin>>n>>k;
	auto go = [&](this auto &&self,unsigned t)->void{
		if(t==1) cout<<k<<" ";
		else if(t==2) cout<<k<<" "<<k<<" ";
		else
		{
			int w = bit_width(t);
			if(t == (1<<(w-1)))
			{
				for(int i =1;i<=t;i++)
					cout<<k<<" ";
			}
			else
			{
				unsigned x = t - (1<<(w-1));
				self(x);
				for(int i = 1;i<=t-2*x;i++)
					cout<<0<<" ";
				self(x);
			}
		}
	};
	go(n);
	cout<<endl;
}
cpp

方法二:二项式系数的模 2 形式#

  • 异或操作的性质使得魔法三角形的每一行实际上是一个 二项式系数的模 2 形式
  • 具体来说,第 n 行的第 j 个元素的值取决于 (n1j1)mod2\tbinom{n-1}{j-1}mod2 二项式系数(n1j1)mod2\tbinom{n-1}{j-1}mod2 可以通过位运算来计算 当且仅当(n1)&(j1)==(j1)(n-1)\&(j-1)==(j-1) 时成立

(nk)\tbinom{n}{k}逐位比较 n 和 k 的二进制表示:

  • 如果 k的某一位为 1,而 n的对应位为 0,则模2为0
  • 否则,模2为1
//jiangly
void solve() {
    int n, k;
    cin >> n >> k;
    for (int i = 0; i < n; i++) {
        cout << (((n - 1) & i) == i ? k : 0) << " \n"[i == n - 1];
    }
}
cpp
魔法三角形以及二项式系数的模2形式
https://astro-pure.js.org/blog/%E8%A1%A5%E9%A2%98%E8%AE%B0%E5%BD%95/%E9%AD%94%E6%B3%95%E4%B8%89%E8%A7%92%E5%BD%A2%E4%BB%A5%E5%8F%8A%E4%BA%8C%E9%A1%B9%E5%BC%8F%E7%B3%BB%E6%95%B0%E7%9A%84%E6%A8%A12%E5%BD%A2%E5%BC%8F
Author zh
Published at February 26, 2025