题目暂时没刷够,写的都是lyd书上的,而且自己都不会我好菜啊。所以也没什么好说的。
但是这个类型依然很重要,因为我全不会。
计数DP
感觉相比之下更像是带有数学组合色彩的递推?可能是做题少了。以后总结吧。
1.CF559C Gerald and Giant Chess
$棋盘有一些黑格子(个数少),剩下为白格子(很多),从左上角往下或往右走到右下角,不经过黑格子方案个数。$
主要还是要强调设计状态避免子问题重叠。设计组合计数,感觉自己该回pj组修炼了。
1 #include<bits/stdc++.h> 2 #define dbg(x) cerr<<#x<<" = "<<x<<endl; 3 using namespace std; 4 typedef long long ll; 5 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;} 6 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;} 7 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 8 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 9 template<typename T>inline T read(T&x){ 10 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 11 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 12 } 13 const int N=2000+7,P=1e9+7,MAXN=200000+3; 14 inline int fpow(int x,int p){int ret=1;for(;p;p>>=1,x=x*1ll*x%P)if(p&1)ret=ret*1ll*x%P;return ret;} 15 struct thx{ 16 int x,y; 17 inline bool operator <(const thx&orz)const{return x^orz.x?x<orz.x:y<orz.y;} 18 }a[N]; 19 int f[N],fac[MAXN],inv[MAXN]; 20 int h,w,n; 21 inline void preprocess(){fac[0]=inv[0]=1;for(register int i=1;i<=200000;++i)fac[i]=fac[i-1]*1ll*i%P,inv[i]=fpow(fac[i],P-2);} 22 inline void inc(int&A,int b){A+=b;A>=P?A-=P:0;} 23 inline int C(int i,int j){return fac[i]*1ll*inv[j]%P*inv[i-j]%P;} 24 25 int main(){//freopen("tmp.in","r",stdin);freopen("tmp.out","w",stdout); 26 read(h),read(w),read(n); 27 for(register int i=1;i<=n;++i)read(a[i].x),read(a[i].y); 28 a[++n].x=h,a[n].y=w;preprocess();sort(a+1,a+n+1);f[0]=1; 29 for(register int i=1;i<=n;++i){ 30 for(register int j=1;j<i;++j)if(a[j].y<=a[i].y){ 31 inc(f[i],f[j]*1ll*C(a[i].x-a[j].x+a[i].y-a[j].y,a[i].x-a[j].x)%P); 32 } 33 f[i]=(C(a[i].x+a[i].y-2,a[i].x-1)-f[i]+P)%P; 34 } 35 printf("%d\n",f[n]); 36 return 0; 37 }
View Code
2.poj1737 Connected Graph
求n个点无向连通图方案数。
强调将状态做到不可分割。希望加深印象。
挂一下自己一开始没有力求将问题反过来思考(互补思想)以及没有把状态再拆散。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 using namespace std; 6 typedef unsigned long long ull; 7 typedef double db; 8 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;} 9 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;} 10 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 11 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 12 template<typename T>inline T read(T&x){ 13 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 14 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 15 } 16 inline ull fpow(int x,int p){ull res=1;for(;p;p>>=1,x=x*x)if(p&1)res=res*x;return res;} 17 int k; 18 ull f[52],typ[52],vis[52],fac[52],q,ret,a[52],len,C[52][52]; 19 void broke(int x,int rest){ 20 if(!rest){ull rett=ret;for(register int i=1;i<k;++i)if(vis[i]>1)rett/=fac[vis[i]];f[k]+=rett;return;} 21 for(register int i=1;i<=rest;++i)if(i<=x)++vis[i],a[++len]=i,ret*=typ[i]*C[rest][i],broke(i,rest-i),ret/=(typ[i]*C[rest][i]),--vis[i],--len; 22 } 23 24 int main(){//freopen("tmp.in","r",stdin);freopen("tmp2.out","w",stdout); 25 f[1]=f[2]=1;typ[1]=1,typ[2]=3;fac[0]=1; 26 for(register int i=1;i<=50;++i)fac[i]=i*fac[i-1]; 27 C[1][1]=C[1][0]=C[0][0]=1; 28 for(register int i=2;i<=50;++i){ 29 C[i][0]=1; 30 for(register int j=1;j<=i;++j)C[i][j]=C[i-1][j-1]+C[i-1][j]; 31 } 32 for(k=3;k<=50;++k){ 33 ret=1;broke(k-1,k-1);typ[k]=f[k]*(fpow(2,k)-1); 34 } 35 }
错误笔记:↓压位高精空间开炸了,或者说poj空间限制小了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<vector> 6 using namespace std; 7 typedef long long ll; 8 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;} 9 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;} 10 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 11 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 12 template<typename T>inline T read(T&x){ 13 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 14 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 15 } 16 const ll base=1e8; 17 struct thx{ 18 ll a[700],len; 19 thx(){len=0,memset(a,0,sizeof a);} 20 inline void tql(int x){a[++len]=x;} 21 inline thx operator -(const thx&orz)const{ 22 thx c; 23 for(register int i=1;i<=len;++i)c.a[i]+=a[i]-orz.a[i],c.a[i]<0?(c.a[i]+=base,--c.a[i+1]):1; 24 for(register int i=len;i;--i)if(c.a[i])return c.len=i,c; 25 return c.len=1,c; 26 } 27 inline thx operator *(const thx&orz)const{ 28 thx c;c.len=len+orz.len-1; 29 for(register int i=1;i<=orz.len;++i) 30 for(register int j=1;j<=len;++j) 31 c.a[i+j-1]+=a[j]*orz.a[i],c.a[i+j]+=c.a[i+j-1]/base,c.a[i+j-1]%=base; 32 while(c.a[c.len+1])++c.len,c.a[len]+=c.a[len-1]/base,c.a[len-1]%=base;return c; 33 } 34 inline thx operator +(const thx&orz)const{ 35 thx c;c.len=_max(len,orz.len); 36 for(register int i=1;i<=c.len;++i)c.a[i]+=a[i]+orz.a[i],c.a[i+1]+=c.a[i]/base,c.a[i]%=base; 37 while(c.a[c.len+1])++c.len,c.a[len]+=c.a[len-1]/base,c.a[len-1]%=base;return c; 38 } 39 inline void write(){ 40 printf("%lld",a[len]); 41 for(register int i=len-1;i;--i)printf("%08lld",a[i]);puts(""); 42 } 43 }f[52],C[52][52]; 44 inline thx fpow(int p){thx ret,x;x.tql(2),ret.tql(1);for(;p;p>>=1,x=x*x)if(p&1)ret=ret*x;return ret;} 45 int n; 46 47 int main(){//freopen("test.in","r",stdin);freopen("test.out","w",stdout); 48 f[1].tql(1);C[1][0].tql(1),C[1][1].tql(1); 49 for(register int i=2;i<=50;++i){C[i][0].tql(1);for(register int j=1;j<=i;++j)C[i][j]=C[i-1][j]+C[i-1][j-1];} 50 for(register int i=2;i<=50;++i){ 51 f[i]=fpow(i*(i-1)>>1); 52 for(register int j=1;j<=i-1;++j)f[i]=f[i]-(f[j]*C[i-1][j-1]*fpow((i-j)*(i-j-1)>>1));//f[i].write(); 53 } 54 while(read(n))f[n].write(); 55 return 0; 56 }
3.poj1037 A decorative fence
思想很重要的一道题,为数位DP打基础。不多说,看lyd书去。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #define dbg(x) cerr<< #x <<" = "<< x <<endl 7 using namespace std; 8 typedef long long ll; 9 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;} 10 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;} 11 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 12 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 13 template<typename T>inline T read(T&x){ 14 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 15 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 16 } 17 const int N=22; 18 ll f[N][N][2],k; 19 int T,n,p,len; 20 inline void dp(){ 21 f[1][1][1]=f[1][1][0]=1; 22 for(register int i=2;i<=20;++i)for(register int j=1;j<=i;++j){ 23 for(register int l=1;l<=j-1;++l)f[i][j][1]+=f[i-1][l][0]; 24 for(register int l=j;l<=i-1;++l)f[i][j][0]+=f[i-1][l][1]; 25 } 26 } 27 int vis[N]; 28 29 int main(){//freopen("test.in","r",stdin);freopen("test.out","w",stdout); 30 read(T);dp();while(T--){ 31 read(n),read(k);memset(vis,0,sizeof vis); 32 for(register int i=1;i<=n;++i){ 33 if(k<=f[n][i][1]){p=1,vis[len=i]=1;break;} 34 k-=f[n][i][1]; 35 if(k<=f[n][i][0]){p=0,vis[len=i]=1;break;} 36 k-=f[n][i][0]; 37 } 38 printf("%d",len);p^=1;int rk=0; 39 for(register int i=2;i<=n;++i,rk=0,p^=1){ 40 for(register int j=1;j<=n;++j) 41 if(!vis[j]){ 42 ++rk;//dbg(rk),dbg(j);dbg(k); 43 if(!p&&j<len||p&&j>len){ 44 if(k<=f[n-i+1][rk][p]){vis[len=j]=1;break;} 45 k-=f[n-i+1][rk][p]; 46 } 47 } 48 printf(" %d",len); 49 } 50 puts(""); 51 } 52 return 0; 53 }