浅谈杨辉三角【复习】
杨辉三角,是二项式系数在三角形中的一种几何排列。
顾定义思用途:二项式定理和排列数预处理
重点在于它的性质(说不定就无意间考了):
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
一:第n行的元素个数有n个;!
二:第n行的所有元素之和为2^n-1^;!!!!
三: 第n行第m个数的值为C(n-1, m-1),其中C为组合数;!!
四:(a+b)^n^ 展开后的各项系数等于第n+1行的值;!!
五:第n行第m个数的奇偶判断,及C(n-1,m-1)的奇偶判断:(m-1)&(n-1)==(m-1)? 奇 : 偶;!!!!!!
例题一:
http://acm.hdu.edu.cn/showproblem.php?pid=6143
题目大意:
一个人的名字有名和姓,名和姓上各有n个字符位置,每个位置的字符从m个字符里面选择。问你有多少个人的名字其名和姓上没有相同的字符。(名或姓内部可以重复)
分析:
考虑第一组盒子,假设用了i种颜色的球,
那么设f(i)为用i种颜色的球(每种颜色必须用到)填n个盒子的种数,显然f(1)=1
则f(i)=i^n^-c(1,i)×f(1)-c(2,i)×f(2)-....-c(i-1,i)×f(i-1)
code:
#include<iostream> #include<string.h> #include<algorithm> using namespace std; #define mods 1000000007 int n,m; long long _power(long long a ,long long b) //快速幂 { long long res=1; while(b) { if(b & 1) res =res*a%mods; a =a*a%mods; b>>=1; } return res; } long long C[2005][2005]; long long f[2005]; //用用i种颜色的球(每种颜色必须用到)填n个盒子的种数 void calculateC() { for(int i=1;i<=2005;i++) { C[0][i]=C[i][i]=1; for(int j=1;j<i;j++) { C[j][i]=(C[j-1][i-1]+C[j][i-1])%mods; //用动态规划求出组合数的转移方程 } } } void solve() { f[1]=1; for(int i=2;i<=n;i++) { long long temp=0; for(int j=1;j<i;j++) { temp=(temp+(C[j][i]*f[j])%mods)%mods; } f[i]=(_power(i,n)-temp+mods)%mods; } int cnt; long long ans=0; int k=m<=n?m-1:n; for(int i=1;i<=k;i++) { cnt=(((C[i][m]*f[i])%mods)*_power(m-i,n))%mods; ans+=cnt; ans%=mods; } cout<<ans<<endl; } int main() { int t; cin>>t; calculateC(); while(t--) { cin>>n>>m; solve(); } return 0; }
后续:这个题不简单
例题二
http://acm.hdu.edu.cn/showproblem.php?pid=6129
题目大意:给你一个数列a[1], a[2], a[3], a[4], ... , a[n],操作一次后变为a[1], a[1] ^ a[2], a[1] ^ a[2] ^ a[3], ..., a[1] ^ a[2] ^ a[3] ^...^a[n],让你计算出m次操作后的数列(m<=1e9)
分析:
先不管那么多,看到1e9,打表找规律


code:
#include <cstdio> #include <cmath> #include <iostream> #include <algorithm> #include <vector> #include <stack> #include <cstring> #include <queue> #include <set> #include <string> #include <map> #include <climits> #define PI acos(-1) using namespace std; typedef long long ll; typedef double db; const int maxn = 2e5 + 5; const int mod = 1e9 + 7; const int INF = 1e8 + 5; const ll inf = 1e15 + 5; const db eps = 1e-6; int a[maxn], b[maxn]; void solve() { int n, m; scanf("%d%d", &n, &m); memset(b, 0, sizeof(b)); memset(a, 0, sizeof(a)); for (int i=1; i<=n; i++) scanf("%d", &a[i]); for (int i=1; i<=n; i++) { int x=i+m-2, y=i-1; if ((x&y)==y) { for (int j=i; j<=n; j++) b[j]^=a[j-i+1]; } } for (int i=1; i<=n; i++) { if (i-1) printf(" "); printf("%d", b[i]); } puts(""); } int main() { int t = 1, cas = 1; scanf("%d", &t); while(t--) { solve(); } return 0; }