B - 系数
这个题目证明方法暂时没有想出来,但是已经可以通过打表的方式解决掉了。
化简
首先 , 在取模的意义下
然后我所要的第 k 项就是
那么只要求出 最后的组合数关于 3 取模的值即可。
首先有如下的打表代码 。
打表
#include<iostream>
using namespace std;
int c[1000][1000];
int main(){
for(int i = 0 ; i <= 90 ; i ++){
printf("%3d : ",i);
for(int j = 0 ; j <= i ; j ++){
if(i == j || j == 0) c[i][j] = 1;
else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % 3;
// if(i % 2 == 0)
// printf("%d ",c[i][j]);
if(c[i][j] == 0) printf("- ");
else if(c[i][j] == 1) printf("+ ");
else if(c[i][j] == 2) printf("| ");
}
printf("\n");
}
return 0;
} 为了便于观察嘛 , 我们把 0 打成 "-" , 1 打成 "+" , 2 打成 "|"
得到如下的一张表
那么这个关系就很明显咯,这个题目显然是要用分形的方法来做。
找规律
我们首先可以发现,每个减号的三角形总是倒着的,而且它们开始的那一边总是 有 或是
这样的形式。并且它们的结尾恰巧就是上一条边减去 1.
由此我们就可以得到初步的规律。它们关于 3 的 k 次幂分形。
然后我们分为两块来观察
第一块 :
第二块 :
一、
首先看第一块,我们发现这个图形有两个三角形组成,全为减号的三角形和不全为 0 的三角形
然后这个不全为 0 的三角形又刚好是减号三角形上面那一块三角形。
因此,在这里,它的规律就是,如果遇到中间那块三角形,则返回 0 反之则返回它上面的三角形。
二、
然后再看第二块,我们发现这是由 3 种三角形组成
首先判断,全为 0 的三角形返回零
然后,我们发现两边的三角形刚好就是第一块两边的三角形,第一块两边的三角形又是上面的三角形,因此我们直接返回到上面的三角形即可。
最后,最中间的三角形和两边的三角形差不多,但有变化。
其中 + --> | , | --> + 。
转化为数字就是 1 --> 2 , 2 --> 1。
也就是 (3 - x) % 3 的值。
0 在这个情况下也成立。
那么返回到上面的三角形。并且设置一个判断,是否改变。
好 , 规律到这里也就找完了。
出结果。
由于题目中的答案要的是
那么我们在判断 k 的奇偶即可。
AC 代码
不知道为什么非要我打表打到100,否则就段错误。
#include<iostream>
#define ll long long
using namespace std;
int c[110][110];
int solve(ll x,ll y,bool f){ // 2 --> 1 | 1 --> 2
if(x <= 100 && y <= 100){
if(f) return (3 - c[x][y]) % 3;
return c[x][y];
}
ll s = 81;
while(s <= x) s*=3; s /= 3;
if(x >= s && x < s * 2){
if(y > x - s && y < s) return 0;
else return solve(x % s,y % s,f);
}
else{
if(y >= s && y < s * 2) return solve(x - s,y % s, !f);
return solve(x - s,y % s,f);
}
}
int main(){
for(int i = 0 ; i <= 105 ; i ++){
for(int j = 0 ; j <= i ; j ++ ){
if(i == j || j == 0) c[i][j] = 1;
else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % 3;
}
}
int t ; cin >> t;
while(t--){
ll n , k ; cin >> n >> k;
n *= 2;
int s = solve(n,k,0);
if(k & 1) s = (- s + 3) % 3;
cout << s << "\n";
}
return 0;
} 
京公网安备 11010502036488号