20241214北京总结
总结
做题 : \(CEQ\)
授课内容 : 线性代数 生成函数 容斥原理 斯特林数
未理解 : 全部
练习题总结 : 如下 , 自习写的 , 今天主要是现补了一下什么是生成函数
AT_agc016_c [AGC016C] +/- Rectangle
手玩一下两个是 \(Yes\) 的样例 , 有一个朴素的思路 , 就是其他位置全填 \(1\) , 直到这里如果再填 \(1\) 就在 \(h*w\) 的范围为正了 , 那么就强制填一个负数让他变负
所以随着做随着搞一个前缀和就可以了 , 发现没过 , 搓一组反例 1 3 1 2
发现按照我的构造它会变成 1 -2 1, 但是可以做到 2 -3 2 , \(so\)我唐完了
所以把填的数变成一个比较大的还不会导致填出绝对值大于 \(10^9\) 就行,选的 \(500\)
/*
* @Author: 2019yyy
* @Date: 2024-12-14 08:36:36
* @LastEditors: 2019yyy
* @LastEditTime: 2024-12-14 09:04:58
* @FilePath: \code\20241214\agc106C.cpp
* @Description:
*
* I love Chtholly forever
*/
#include<bits/stdc++.h>
using namespace std;
int a[510][510],sum[510][510];
int main(){
int n,m,h,w;
cin>>n>>m>>h>>w;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
if(i>=h and j>=w){
int temp=sum[i][j]-sum[i-h][j]-sum[i][j-w]+sum[i-h][j-w];
//cout<<i<<" "<<j<<" "<<temp<<'\n';
if(temp<0){
a[i][j]=500;
}else{
a[i][j]=-temp-1;
}
}else{
a[i][j]=500;
}
sum[i][j]+=a[i][j];
}
}
if(sum[n][m]<=0){
cout<<"No\n";
return 0;
}
cout<<"Yes\n";
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cout<<a[i][j]<<" ";
}
cout<<'\n';
}
return 0;
}
生成函数
以数列的第 \(n\) 项作为 \(x^n\) 项的系数 , 形式化的: \(F(x)=\displaystyle\sum_na_nx^n\)
如 \(a= \left \langle 1,0,1,0..... \right \rangle\) , 那么 \(F(x)=\displaystyle\sum_nx^{2n}\)
为了化简 , 我们通常会把它变成一个封闭形式
如 \(a= \left \langle 1,0,1,0..... \right \rangle\) , 那么 \(x^2F(x)+1=F(x)\) , 即\(F(x)=\frac{1}{1-x^2}\)
下面给一些常用的 ( 我遇到的 ):
\(F(x)=\displaystyle\sum_nx^{kn}=\frac{1}{1-x^k}\)
\(F(x)=\displaystyle\sum_np^nx^{n}=\frac{1}{1-nx}\) ( 等比数列 )
\(F(x)=\displaystyle\sum_n\binom{m}{n}x^{n}=(1+x)^m\)
在接下来我们需要一些前置知识
广义组合数 广义二项式定理
我们需要有一个前置知识 : 广义二项式定理
我们先来看看广义组合数 , 即:
\(so\) :
若\(n > m >0\)时 , 有 :
接着广义二项式定理 :
对于任意一个\(k\) , 都有 :
所以 , 我们可以求出\(a_n=\binom{m}{n}\) 的生成函数 , 即为
P10780 BZOJ3028 食物
对每一种食物推生成函数
- 承德汉堡 : \(F(x)=\displaystyle\sum_nx^{2n}=\frac{1}{1-x^2}\)
- 可乐 : \(F(x)=x+1\)
- 鸡腿 : \(F(x)=x^2+x+1=\displaystyle\frac{x^3-1}{x-1}\)
- 蜜桃多 : \(F(x)=\displaystyle\sum_nx^{2n+1}=\frac{x}{1-x^2}\)
- 鸡块 : \(F(x)=\displaystyle\sum_nx^{4n}=\frac{1}{1-x^4}\)
- 包子 : \(F(x)=x^3+x^2+x+1=(x+1)(x^2+1)\)
- 土豆片炒肉 : \(F(x)=x+1\)
- 面包:\(3\) 的倍数个 : \(F(x)=\displaystyle\sum_nx^{3n}=\frac{1}{1-x^3}\)
把它们的生成函数全乘到一起 , 发现等于\(\displaystyle\frac{x}{(x-1)^4}\)
之后把这个封闭形式摊开
最后答案就是\(\binom{k+2}{3}=\frac{(k+2)\times\ (k+1)\times k}{6}\) , 最后一边读入一边\(mod\) ( 但我用\(py\)水过了 )
mod=10007
n=int(input())
n=n%mod
ans=n*(n+1)%mod*(n+2)%mod*1668%mod
print(int(ans))
还有一道类似的P2000拯救世界 , 不再过多赘述
[ABC241Ex] Card Deck Score
考虑生成函数
分子可以在\(O(2^n)\)求出 , 分母单独考虑
设 \(G(x)=\prod^n_{i=1}(a_ix-1)^{-1}=\sum^n_{i=1}t_i(a_ix-1)^{-1}\)
把右式通分同乘分母得\(\sum^n_{i=1}(t_i\prod_{j\neq i}a_ix-1)=1\)
我们可以任取 \(16\) 个 \(x\) , 高斯消元
求完 \(t\) 以后卷一下
/*
* @Author: 2019yyy
* @Date: 2024-12-14 16:23:16
* @LastEditors: 2019yyy
* @LastEditTime: 2024-12-14 16:56:30
* @FilePath: \code\20241214\abc241Ex.cpp
* @Description:
*
* I love Chtholly forever
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=998244353;
int a[11000000],b[1100000],f[1100000];
int v[(1<<16)],w[(1<<16)];
int qpow(int x,int y){
int res=1;
while(y){
if(y&1){
res=res*x%mod;
}
x=x*x%mod;
y>>=1;
}
return res;
}
signed main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i];
b[i]++;
}
for(int i=0;i<=(1<<n)-1;i++){
v[i]=1;
for(int j=0;j<=n-1;j++){
if((i>>j)&1){
v[i]=v[i]*((mod-qpow(a[j+1],b[j+1])%mod)%mod)%mod;
w[i]=w[i]+b[j+1];
}
}
}
for(int i=1;i<=n;i++){
int inv=qpow(a[i],mod-2);
f[i]=1;
for(int j=1;j<=n;j++){
if(j==i){
continue;
}
f[i]=f[i]*((1+mod-a[j]*inv%mod)%mod)%mod;
}
f[i]=qpow(f[i],mod-2);
}
int ans=0;
for(int i=0;i<=(1<<n)-1;i++){
if(w[i]>m){
continue;
}
for(int j=0;j<=n-1;j++){
ans=ans+v[i]*f[j+1]%mod*qpow(a[j+1],m-w[i]);
ans%=mod;
}
}
cout<<ans<<'\n';
}
容斥
简单来说 , 思想很简单 , 把有用的贡献算为 \(1\) 或一个常数 , 把没有用的贡献算为 \(0\)
P3266 [JLOI2015] 骗我呢
把这个图拉伸一下 , 变成了切掉两个角的网格图 , 进而变成不过两条直线的网格图
首先考虑只有一条线我们应该怎么做 , 这是一个类似卡特兰数的问题 , 就把终点关于直线对称一下 , 再剪掉到新终点的方案数就行
我们多了一条线这种做法就不太可做了 , 因为可以同时过两条线 , 我们继续应用刚才的容斥思想
即标号过两条线分别为 \(AB\) , 过 \(A\) - 过 \(AB\) + 过 \(ABA\) -.....
那么先过 \(A\) 再过 \(B\) 的要怎么做 , 只要把之前对称出来的点再关于 \(B\) 对称一下就行
/*
* @Author: 2019yyy
* @Date: 2024-12-14 19:25:47
* @LastEditors: 2019yyy
* @LastEditTime: 2024-12-14 22:06:23
* @FilePath: \code\20241214\P3266.cpp
* @Description:
*
* I love Chtholly forever
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
int fac[11000000];
int qpow(int x,int y){
int res=1;
while(y){
if(y&1){
res=res*x%mod;
}
x=x*x%mod;
y>>=1;
}
return res;
}
int inv(int x){
return qpow(x,mod-2);
}
int C(int x,int y){
if(x<0){
return 0;
}
if(x>y){
return 0;
}
return fac[y]*inv(fac[x])%mod*inv(fac[y-x])%mod;
}
int n,m;
void change(int &x,int &y,int val){
swap(x,y);
x-=val;
y+=val;
}
signed main(){
cin>>n>>m;
fac[0]=1;
for(int i=1;i<=3e6+1;i++){
fac[i]=fac[i-1]*i%mod;
}
int x=n+m+1,y=n;
int ans=C(y,x+y);
while(x>=0 and y>=0){
change(x,y,1);
ans+=mod-C(x,x+y);
ans%=mod;
change(x,y,-(m+2));
ans+=C(x,x+y);
ans%=mod;
}
x=n+m+1,y=n;
while(x>=0 and y>=0){
change(x,y,-(m+2));
ans+=mod-C(x,x+y);
ans%=mod;
change(x,y,1);
ans+=C(x,x+y);
ans%=mod;
}
cout<<ans%mod<<'\n';
return 0;
}

浙公网安备 33010602011771号