June/21st/22 校内考试T2 杨辉三角 题解
June/21st/22 校内考试T2 杨辉三角 题解
题目
描述
求杨辉三角前 \(n\) 排的偶数的数量
I/O
Input
一行一个整数 \(n\)
Output
一行一个整数,表示杨辉三角前 \(n\) 排中偶数的数量\(\pmod {(1e6+3)}\)
I/O Example
Input
6
Output
6
Example Explain
如下为杨辉三角的前 \(7\) 行
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
不难数出前 \(6\) 行共有 \(6\) 个偶数
思路分析
本题要求偶数的个数,也就是说和奇偶性有关。而我们知道,奇数 \(+\) 奇数 \(=\) 偶数,奇数 \(+\) 偶数 \(=\) 奇数,偶数 \(+\) 偶数 \(=\) 偶数。
这与异或很像:1^1=0,1^0=1,0^0=0
同时,杨辉三角中偶数的数量 \(=\) 总数 \(-\) 奇数数量
我们不妨用 \(0\) 代表偶数, \(1\) 代表奇数,杨辉三角计算过程中的加法我们换成异或和,列出杨辉三角的前几项,并统计奇数数量:
1 1 项数:2^0,奇数个数:3^0
2 1 1 项数:2^1,奇数个数:3^1
3 1 0 1
4 1 1 1 1 项数:2^2,奇数个数:3^2
5 1 0 0 0 1
6 1 1 0 0 1 1
7 1 0 1 0 1 0 1
8 1 1 1 1 1 1 1 1 项数:2^3,奇数个数:3^3
9 1 0 0 0 0 0 0 0 1
10 1 1 0 0 0 0 0 0 1 1
11 1 0 1 0 0 0 0 0 1 0 1
12 1 1 1 1 0 0 0 0 1 1 1 1
13 1 0 0 0 1 0 0 0 1 0 0 0 1
14 1 1 0 0 1 1 0 0 1 1 0 0 1 1
15 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
16 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 项数:2^4,奇数个数:3^4
我们发现:
- 当 \(n=2^k\) 时,奇数的个数为 \(3^k\) , \(k\in \N\)
- 杨辉三角 形成的图形呈分形几何特征(特别是谢尔宾斯基三角形)
基于这两个特点,我们可以推导出可行的一个算法:
算法设计
- 我们计算出使 \(2^k\le n\) 的最大的 \(k\) ,使 \(ans+=3^k\)
- 使 \(t=n-2^k\)
- 计算出使 \(2^k\le t\) 的最大的 \(k\) ,使 \(ans+=2^1\times 3^k\)
- 重复上述
2.3步,直到 \(t=0\)
那么我们得到的 \(ans\) 即为答案
代码
#include<bits/stdc++.h>
using namespace std;
#define GO(u,v,i) for(register int i=u;i<=v;i++)
template<class t>inline t fr(){
register t num=0,dis=1;
register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')dis=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){num=(num<<1)+(num<<3)+(ch^48);ch=getchar();}
return num*dis;
}
template<class t>inline void fw(t num){
if(num>9)fw(num/10);
putchar(num%10+'0');
}
template<class t>inline void fw(t num,char ch){
if(num<0)num=-num,putchar('-');
fw(num);putchar(ch);
}
typedef long long lld;
lld ans;
const lld mo=1e6+3;
lld n;
inline lld fpow(lld a,lld b){
lld ans=1,x=a;
for(;b;b>>=1){
if(b&1)ans*=x;
x*=x;
}
return ans;
}
inline lld ffpow(lld a,lld b){
lld ans=1,x=a;
for(;b;b>>=1){
if(b&1){
ans*=x;ans%=mo;
}
x*=x;x%=mo;
}
return ans;
}
signed main(){
lld tt=n=fr<lld>();
lld t=1;
lld k=0;
while(t){
lld i=0;
while(tt-fpow(2,i)>=0)t=tt-fpow(2,i++);
i--;
ans+=((fpow(2,k++)%mo)*(ffpow(3,i)%mo))%mo;ans%=mo;
tt=t;
}
if(n%2==0){
ans=(((n/2)%mo)*((n+1)%mo))%mo-ans%mo;
}else{
ans=((((n+1)/2)%mo)*(n%mo))%mo-ans%mo;
}
fw((ans+mo)%mo,'\n');
return 0;
}

浙公网安备 33010602011771号