计数DP/数位DP总结【施工中】

题目暂时没刷够,写的都是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 }
View Code

错误笔记:↓压位高精空间开炸了,或者说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 }
View Code

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 }
View Code

猜你喜欢

转载自www.cnblogs.com/saigyouji-yuyuko/p/10519866.html