1. 程式人生 > >題解——排隊

題解——排隊

div max error urn 沒有 style () 相加 bsp

公式:A(n,n)*A(n+1,2)*A(n+3,m) +    A(n,n)*C(m,1)*A(2,2)*C(n+1,1)*A(n+2,m-1)
分情況討論推出公式
前者為無論何時都合法的,後者為先不合法,然後再合法的(兩個老師先站在一 起,然後一個女生
插進來,所以要把這3個人看成一個整體,然後老師可以左右換,所以乘2,女生    就是m選1,然後整體再插入隊伍
最後得到上面的式子
由於答案較大,所以要寫高精
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define AC 10000
  4 #define R register int
  5
#define D printf("the k is %d\n",k); 6 /*A(n,n)*A(n+1,2)*A(n+3,m) + A(n,n)*C(m,1)*A(2,2)*C(n+1,1)*A(n+2,m-1) 7 分情況討論推出公式 8 前者為無論何時都合法的,後者為先不合法,然後再合法的(兩個老師先站在一 起,然後一個女生 9 插進來,所以要把這3個人看成一個整體,然後老師可以左右換,所以乘2,女生 就是m選1,然後整體再插入隊伍 10 最後得到上面的式子 11 */ 12 int sum2[AC],a[AC],sum1[AC],k,n,m,tot,tot1,tot2,ans[AC];//
每次計 算前將memset a,將高精sum*低精k存入a,然後計算完畢後將a導入sum 13 14 void ADD()//加法 15 { 16 for(R i=1;i<=max(tot1,tot2);i++)//error!!!註意這裏要加到max(tot1,tot2)!!! 17 { 18 ans[i+1]=ans[i+1]+(sum1[i]+sum2[i]+ans[i])/10000; 19 ans[i]=(ans[i]+sum1[i]+sum2[i])%10000; 20 } 21 tot=(tot1+tot2)%10000;
22 while(!ans[tot] && tot>1)--tot;//註意邊界!!! 23 } 24 25 void add1()//乘法1,計算前一部分 26 { 27 memset(a,0,sizeof(a)); 28 for(R i=1;i<=tot1;i++) 29 { 30 a[i+1]=a[i+1]+(a[i]+sum1[i]*k)/10000; 31 a[i]=(a[i]+sum1[i]*k)%10000; 32 } 33 tot1+=1;//因為n和m最大就是2000,所以最多也就加這麽多位了,又因為壓了位,,,所以 34 while(!a[tot1] && tot1>1)--tot1; 35 if(!a[tot1])memset(sum1,0,sizeof(sum1));//如果女生太多了會導致沒有合法情況!! 36 else for(R i=1;i<=tot1;i++) sum1[i]=a[i];//導入sum 37 } 38 39 void add2()//乘法2,計算後一部分 40 { 41 memset(a,0,sizeof(a)); 42 for(R i=1;i<=tot2;i++) 43 { 44 a[i+1]=a[i+1]+(a[i]+sum2[i]*k)/10000; 45 a[i]=(a[i]+sum2[i]*k)%10000; 46 } 47 tot2+=1;//因為n和m最大就是2000,所以最多也就加這麽多位了,又因為壓了位,,,所以 48 while(!a[tot2] && tot2>1)--tot2; 49 if(!a[tot2])memset(sum2,0,sizeof(sum2)); 50 else for(R i=1;i<=tot2;i++) sum2[i]=a[i];//導入sum 51 } 52 53 void work() 54 { 55 sum1[1]=1;//初始值 56 tot1=1; 57 for(R i=2;i<=n;i++)//計算A(n,n),即n! 58 { 59 k=i; 60 add1(); 61 } 62 k=n; 63 add1(); 64 k=n+1;//分開乘,不然k太大會爆 65 add1(); 66 k=n+3; 67 for(R i=1;i<=m;i++)//計算A(n+3,m) 68 { 69 add1(); 70 --k; 71 } 72 //一二部分分割線~~~~~~~~~~~~~~~ 73 sum2[1]=2*(n+1);//不會破萬,所以直接放在第一個即可 74 tot2=1; 75 k=m; 76 add2(); 77 for(R i=2;i<=n;i++) 78 { 79 k=i; 80 add2(); 81 } 82 k=n+2; 83 for(R i=1;i<=m-1;i++) 84 { 85 add2(); 86 --k; 87 } 88 ADD();//最後把sum1和sum2相加得到ans 89 printf("%d",ans[tot--]); 90 for(R i=tot;i>=1;i--)printf("%04d",ans[i]); 91 /*printf("\n"); 92 while(!sum1[tot1])tot1--; 93 printf("%d",sum1[tot1]); 94 for(R i=tot1-1;i>=1;i--)printf("%04d",sum1[i]);*/ 95 } 96 97 int main() 98 { 99 freopen("in.in","r",stdin); 100 scanf("%d%d",&n,&m); 101 work(); 102 fclose(stdin); 103 return 0; 104 }

 

題解——排隊