CSDN 高校俱乐部/英雄会 题目;
设数组a包含n个元素恰好是0..n - 1的一个排列,给定b[0],b[1],b[2],b[3]问有多少个0..n-1的排列a,满足(a[a[b[0]]]*b[0]+a[a[b[1]]]*b[1]+a[a[b[2]]]*b[2]+a[a[b[3]]]*b[3])%n==k ?
输入包含5个参数:N,K,B0,B1,B2,B3,其中 4<= N<12, 0 <= K,B0,B1,B2,B3 < N
单全排列超时代码:
#include <stdio.h> #include <string.h> int b[5]; int c[5]; int a[15]; int aa[15]; int vis[15]; int n, sum, k; int B_same_num(int b[]){ int i, j; int p = 4; for(i=0;i<3;++i){ if(b[i] == -1) continue; for(j=i+1;j<4;++j) if(b[i] == b[j]){ b[j] = -1; --p; } } return p; } void reset(int b[]){ int i, j; for(i=j=0; j < 4; ++j){ if(b[j] != -1) c[i++] = b[j]; } } void dfs(int s, int num) { int i; if(s == n) { if(4 == num) if( (c[0]*a[a[0]] + c[1]*a[a[1]] + c[2]*a[a[2]] + c[3]*a[a[3]])%n == k ) ++sum; if(3 == num) if( (c[0]*a[0] + c[1]*a[1] + 2 * c[2]*a[2])%n == k ) ++sum; if(2 == num) if( (c[0]*a[0] + 3 * c[1]*a[1])%n == k ) ++sum; if(1 == num) if( (4 * c[0]*a[0])%n == k ) ++sum; return; } for(i = 0; i < n; i++) { if(vis[i]) continue; vis[i] = 1; a[s] = i; dfs(s+1, num); vis[i] = 0; } } int main(int argc, char const *argv[]) { int t, i; scanf("%d", &t); while(t--){ sum = 0; scanf("%d %d", &n, &k); for(i=0;i<4;++i) scanf("%d", &b[i]); int num = B_same_num(b); reset(b); dfs(0, num); printf("%d\n", sum); } return 0; }
双全排列改进后AC的代码:
#include <stdio.h> #include <string.h> int b[5]; int c[5]; int a[15]; int d[15]; int sui[15]; int vis[15]; int vis1[15]; int arr[15]; int jiecheng[20]; int n, sum, k; void _jiecheng(){ jiecheng[0] =1; jiecheng[1] =1; jiecheng[2] =2; jiecheng[3] =6; jiecheng[4] =24; jiecheng[5] =120; jiecheng[6] =720; jiecheng[7] =5040; jiecheng[8] =40320; jiecheng[9] =362880; jiecheng[10] =3628800; jiecheng[11] =39916800; jiecheng[12] =479001600; } void init(){ int i; for(i=0;i<15;++i) arr[i] = 0; } int B_same_num(int b[]){ int i, j; int p = 4; for(i=0;i<3;++i){ if(b[i] == -1) continue; for(j=i+1;j<4;++j) if(b[i] == b[j]){ b[j] = -1; --p; } } return p; } void reset(int b[]){ int i, j; for(i=j=0; j < 4; ++j){ if(b[j] != -1) c[i++] = b[j]; } } void suiji(int s, int num, int b_num) { int i, j; int dd; dd = n - num - b_num; if(s == num) { j=0; for(i = 0; i < b_num; i++){ if(arr[a[c[i]]] == 1) continue; else { a[a[c[i]]] = sui[j++]; } } if(4 == b_num){ if( (c[0]*a[a[c[0]]] + c[1]*a[a[c[1]]] + c[2]*a[a[c[2]]] + c[3]*a[a[c[3]]])%n == k ){ sum+=jiecheng[dd]; } } if(3 == b_num) if( (c[0]*a[a[c[0]]] + c[1]*a[a[c[1]]] + 2 * c[2]*a[a[c[2]]])%n == k ) sum+=jiecheng[dd]; if(2 == b_num) if( (c[0]*a[a[c[0]]] + 3 * c[1]*a[a[c[1]]])%n == k ) sum+=jiecheng[dd]; if(1 == b_num) if( (4 * c[0]*a[a[c[0]]])%n == k ) sum+=jiecheng[dd]; return; } for(i = 0; i < n; i++) { if(vis1[i]) continue; if(vis[i]) continue; vis1[i] = 1; sui[s] = i; // printf("sui : %d\n", sui[s]); suiji(s+1, num, b_num); vis1[i] = 0; } } int arr_num(int num){ int dd = 0; int i; for(i=0;i<num;++i) if(arr[a[c[i]]] == 1) continue; else ++dd; return dd; } void dfs(int s, int num) { int i, t; if(s == num) { init(); for(i=0;i<num;++i){ a[c[i]] = d[i]; arr[c[i]] = 1; } t = arr_num(num); suiji(0, t, num); return; } for(i = 0; i < n; i++) { if(vis[i]) continue; vis[i] = 1; d[s] = i; dfs(s+1, num); vis[i] = 0; } } int main(int argc, char const *argv[]) { int t, i; scanf("%d", &t); while(t--){ sum = 0; _jiecheng(); scanf("%d %d", &n, &k); for(i=0;i<4;++i) scanf("%d", &b[i]); int num = B_same_num(b); reset(b); dfs(0, num); printf("%d\n", sum); } return 0; }
精简版 代码:
#include <stdio.h> #include <string.h> int a[12]; int b[4]; int N, K, ans; int v[12]; int fac[14]; void factorial(){ int i; fac[0] = 1; for(i=1;i<=12;++i) fac[i] = fac[i-1]*i; } void dfs2(int s){ int t; if(s == 4){ if ((a[a[b[0]]]*b[0]+a[a[b[1]]]*b[1]+a[a[b[2]]]*b[2]+a[a[b[3]]]*b[3])%N==K){ t = 0; int i; for(i=0;i<N;++i) if(a[i] == -1) ++t; ans += fac[t]; } return; } if(a[a[b[s]]] != -1) dfs2(s+1); else{ int i; for(i=0;i<N;++i) if(!v[i]){ v[i] = 1; a[a[b[s]]] = i; dfs2(s+1); v[i] = 0; a[a[b[s]]] = -1; } } } void dfs(int s){ int i; if(s == 4){ dfs2(0); return; } if(a[b[s]] != -1) dfs(s+1); else{ for(i=0;i<N;++i) if(!v[i]){ v[i] = 1; a[b[s]] = i; dfs(s+1); v[i] = 0; a[b[s]] = -1; } } } int main(int argc, char const *argv[]) { int i; scanf("%d%d%d%d%d%d", &N, &K, &b[0], &b[1], &b[2], &b[3]); ans = 0; memset(v, 0, sizeof(v)); for(i=0;i<12;++i) a[i] = -1; factorial(); dfs(0); printf("%d\n", ans); return 0; }
测试数据 :
#include <stdio.h> #include <string.h> int howmany (int N,int K,int B0,int B1,int B2,int B3) { if(N==4 && K==0 && B0==3 && B1==2 &&B2==1 &&B3==0) return 4; if(N==5 && K==2 && B0==1 && B1==2 &&B2==3 &&B3==4) return 40; if(N==6 && K==4 && B0==5 && B1==4 &&B2==3 &&B3==2) return 78; if(N==7 && K==6 && B0==6 && B1==4 &&B2==2 &&B3==0) return 684; if(N==8 && K==1 && B0==0 && B1==1 &&B2==2 &&B3==3) return 5454; if(N==9 && K==3 && B0==4 && B1==8 &&B2==1 &&B3==2) return 44028; if(N==10 && K==5 && B0==3 && B1==7 &&B2==9 &&B3==0) return 349776; if(N==11 && K==7 && B0==3 && B1==1 &&B2==8 &&B3==9) return 3651984; if(N==11 && K==0 && B0==0 && B1==0 &&B2==0 &&B3==0) return 39916800; if(N==11 && K==5 && B0==4 && B1==3 &&B2==2 &&B3==1) return 3662976; return 0; }
PS : 和别人的代码根本无法媲美。。以后在重新改进一下这份代码!