A 错排公式 d[n] = (n-1)*(d[n-1]+d[n-2]);
#include<stdio.h> typedef long long LL; LL d[110]; const int mod = 1e9+7; void init(){ d[1] = 0; d[2] = 1; for(int i = 3; i <= 100; i++){ d[i] = 1LL*(i-1)*(d[i-1]+d[i-2])%mod; } } int main(){ init(); int T; scanf("%d",&T); while( T-- ){ int n; scanf("%d", &n); printf("%I64d\n", d[n] ); } return 0; }
B 每次至少有个国家恐慌值+1,超过5则必定在有限次以内。。。直接暴力BFS/DFS。。
C ,D 跪了。
E
模型一,最大独立点集 , 又 最大团中顶点数量 = 补图中最大独立点数
可以用优化的 Bron-Kerbosch 算法求解最大团中顶点数量
#include<cstdio> #include<cstring> #define N 1010 bool flag[N], a[N][N]; int ans, cnt[N], group[N], n, vis[N]; // 最大团: V中取K个顶点,两点间相互连接 // 最大独立集: V中取K个顶点,两点间不连接 // 最大团数量 = 补图中最大独立集数 bool dfs( int u, int pos ){ int i, j; for( i = u+1; i <= n; i++){ if( cnt[i]+pos <= ans ) return 0; if( a[u][i] ){ // 与目前团中元素比较,取 Non-N(i) for( j = 0; j < pos; j++ ) if( !a[i][ vis[j] ] ) break; if( j == pos ){ // 若为空,则皆与 i 相邻,则此时将i加入到 最大团中 vis[pos] = i; if( dfs( i, pos+1 ) ) return 1; } } } if( pos > ans ){ for( i = 0; i < pos; i++ ) group[i] = vis[i]; // 最大团 元素 ans = pos; return 1; } return 0; } void maxclique() { ans=-1; for(int i=n;i>0;i--) { vis[0]=i; dfs(i,1); cnt[i]=ans; } } int dir[8][2] = { {1,1},{-1,-1},{1,-1},{-1,1} ,{2,0},{-2,0},{0,2},{0,-2} }; int mp[110][11], num[110][11]; int main(){ int nn, m; while( scanf("%d%d",&nn,&m) != EOF){ int p = 0; memset( num, 0, sizeof(num)); memset( a, 0, sizeof(a)); for(int i = 0; i < nn; i++) for(int j = 0; j < m; j++){ scanf("%d",&mp[i][j]); if( mp[i][j] ) num[i][j] = ++p; } for(int i = 0; i < nn; i++){ for(int j = 0; j < m; j++){ if( mp[i][j] ) for(int k = 0; k < 8; k++){ int x = i+dir[k][0], y = j+dir[k][1]; if( (x>=0)&&(x<nn)&&(y>=0)&&(y<m) && mp[x][y] ) a[ num[i][j] ][ num[x][y] ] = a[ num[x][y] ][ num[i][j] ] = 1; } } } n = p; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if( i == j ) a[i][j] = 0; else a[i][j] ^= 1; maxclique(); printf("%d\n", ans ); } return 0; }