都是经典题了吧。。我好无聊。。
4806-1801是双倍经验。。DP方程看代码吧。。
1 /* http://www.cnblogs.com/karl07/ */ 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <algorithm> 7 using namespace std; 8 9 #define ll long long 10 //#define P 9999973 //bzoj1801 11 #define P 999983 //bzoj4806 12 #define C(x) ((x)*(x-1)/2) 13 int n,m; 14 ll f[105][105][105]; 15 16 int main(){ 17 scanf("%d%d",&n,&m); 18 f[0][0][0]=1; 19 for (int i=1;i<=n;i++){ 20 for (int j=0;j<=m;j++){ 21 for (int k=0;k<=m-j;k++){ 22 f[i][j][k]+=f[i-1][j][k]; 23 if (j>=1) f[i][j][k]+=f[i-1][j-1][k]*(m-j-k+1); 24 if (k>=1 && j<=m-1)f[i][j][k]+=f[i-1][j+1][k-1]*(j+1); 25 if (j>=2) f[i][j][k]+=f[i-1][j-2][k]*C(m-j-k+2); 26 if (k>=2 && j<=m-2)f[i][j][k]+=f[i-1][j+2][k-2]*C(j+2); 27 if (j>=1 && k>=1) f[i][j][k]+=f[i-1][j][k-1]*j*(m-j-k+1); 28 f[i][j][k]%=P; 29 } 30 } 31 } 32 ll ans=0; 33 for (int i=0;i<=m;i++){ 34 for (int j=0;j<=m-i;j++){ 35 ans+=f[n][i][j]; 36 ans%=P; 37 } 38 } 39 printf("%lld ",ans); 40 return 0; 41 }
就是 max(m,n) C min (m,n)
1 /* http://www.cnblogs.com/karl07/ */ 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <algorithm> 7 using namespace std; 8 struct INT { 9 int b,a[60]; 10 INT (){b=0; for (int i=0;i<=50;i++) a[i]=0;} 11 }; 12 int A,B,c,n,m; 13 int P[1000005],p[1000005],cnt[1000005],ip[1000005]; 14 INT Int(int x){ 15 INT a; 16 for (a.b=0 ; x ; a.a[++a.b]=x%10,x/=10); 17 return a; 18 } 19 20 INT operator * (const INT &x,const INT &y){ 21 INT a; 22 a.b=min(50,x.b+y.b-1); 23 for (int i=1;i<=x.b;i++) for (int j=1;j<=y.b;j++) if (i+j-1<=50) a.a[i+j-1]+=x.a[i]*y.a[j]; 24 for (int i=1;i<=a.b;a.b+=(i==a.b && a.a[i+1] && i+1<=50),i++) a.a[i+1]+=a.a[i]/10,a.a[i]%=10; 25 for (;a.a[a.b]==0 && a.b!=1; a.b--); 26 return a; 27 } 28 29 void print_INT(INT x){ 30 for (int i=min(x.b,50);i>=1;i--) printf("%d",x.a[i]); 31 puts(""); 32 } 33 34 void Prime(int n){ 35 for (int i=2;i<=n;i++){ 36 if (!P[i]){ 37 p[++c]=i,ip[i]=c; 38 for (int j=i+i;j<=n;j+=i) P[j]=1; 39 } 40 } 41 } 42 43 void pt(int x) { 44 printf("%d ",x); 45 } 46 47 void fac(int x,int y){ 48 for (int i=1;i<=c && P[x];i++) while (!(x%p[i])) x/=p[i],cnt[i]+=y; 49 cnt[ip[x]]+=y; 50 } 51 52 INT ans=Int(1); 53 int main(){ 54 scanf("%d%d",&A,&B); 55 n=max(A,B),m=max(max(A,B)-min(A,B),min(A,B)); 56 Prime(n); 57 for (int i=m+1;i<=n;i++) fac(i,1); 58 for (int i=2;i<=n-m;i++) fac(i,-1); 59 for (int i=1;i<=c;i++) while (cnt[i]--) ans=ans*Int(p[i]); 60 print_INT(ans); 61 return 0; 62 }
黑白染色然后匈牙利
1 /* http://www.cnblogs.com/karl07/ */ 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <algorithm> 7 using namespace std; 8 9 struct edge{ 10 int next,to; 11 }e[1000005]; 12 int ade,n,m,cnt,T,c; 13 int x[]={1,2,-1,-2,-1,2,1,-2}; 14 int y[]={2,1,-2,-1,2,-1,-2,1}; 15 int mp[205][205],id[205][205],first[1000005],vis[1000005],match[1000005]; 16 17 void addedge(int x,int y){ 18 e[++ade].next=first[x]; 19 e[ade].to=y; 20 first[x]=ade; 21 } 22 23 bool check(int x,int y){ 24 return (x>=1 && x<=n && y>=1 && y<=m && !mp[x][y]); 25 } 26 27 #define s e[x].to 28 bool hungary(int p){ 29 for (int x=first[p];x;x=e[x].next){ 30 if (vis[s]!=T){ 31 vis[s]=T; 32 if (!match[s] || hungary(match[s])) {match[s]=p; return 1;} 33 } 34 } 35 return 0; 36 } 37 #undef s 38 39 int main(){ 40 scanf("%d%d",&n,&m); 41 for (int i=1;i<=n;i++){ 42 for (int j=1;j<=m;j++){ 43 scanf("%d",&mp[i][j]); 44 cnt+=(!mp[i][j]); 45 id[i][j]=++c; 46 } 47 } 48 for (int i=1;i<=n;i++) 49 for (int j=1;j<=m;j++) 50 if (((i+j)&1) && !mp[i][j])for (int k=0;k<8;k++) if (check(i+x[k],j+y[k])) addedge(id[i][j],id[i+x[k]][j+y[k]]); 51 for (int i=1;i<=n;i++){ 52 for (int j=1;j<=m;j++){ 53 if (!mp[i][j] && ((i+j)&1)){ 54 T=id[i][j]; 55 cnt-=hungary(T); 56 } 57 } 58 } 59 printf("%d ",cnt); 60 return 0; 61 }
直接dfs
1 /* http://www.cnblogs.com/karl07/ */ 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <algorithm> 7 using namespace std; 8 9 int n,ans; 10 int ban[20][20],y[20],a[40],b[40]; 11 12 void dfs(int i){ 13 if (i>n) {ans++; return;} 14 for(int j=1;j<=n;j++) if (!(ban[i][j] || y[j] || a[i+j-1] || b[n-i+j] )){ 15 y[j]=a[i+j-1]=b[n-i+j]=1; 16 dfs(i+1); 17 y[j]=a[i+j-1]=b[n-i+j]=0; 18 } 19 } 20 21 int main(){ 22 scanf("%d",&n); 23 for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) scanf("%d",&ban[i][j]); 24 dfs(1); 25 printf("%d ",ans); 26 return 0; 27 }