sdut 2878 圆圈
[ 题目描述]
现在有一个圆圈, 顺时针标号分别从 0 到 n-1, 每次等概率顺时针走一步或者逆时针走一步,
即如果你在 i 号点,你有 1/2 概率走到((i-1)mod n)号点,1/2 概率走到((i+1)mod n)号点。问
从 0 号点走到 x 号点的期望步数。
[ 输入]
第一行包含一个整数 T,表示数据的组数。
接下来有 T 行,每行包含两个整数 n, x。
T<=10, 0<=x<n<=300;
[ 输出]
对于每组数据,输出一行,包含一个四位小数表示答案。
[ 样例输入]
3
3 2
5 4
10 5
[ 样例输出]
2.0000
4.0000
25.0000
[ 数据范围]
对于 30% 的数据,n<=20
对于 50% 的数据,n<=100
对于 70% 的数据,n<=200
对于 100%的数据,n<=300
期望公式:
E[x]=0 (x==0);
E[x]=0.5*(E[x-1]+1)+0.5*(E[x+1]+1); (x!=0)
移项得,-E[i-1]*0.5+E[i]-E[i+1]*0.5=1
n 个方程高斯消元求解。
但有一个奇技淫巧
我们发现答案只有整数,于是打表,发现ans=(n-x)*x
%%%%%YZD佬orz
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 int main() 6 { 7 freopen("circle.in","r",stdin); 8 freopen("circle.out","w",stdout); 9 int T; 10 cin>>T; 11 while(T--) 12 { 13 int a,b; 14 cin>>a>>b; 15 cout<<b*(a-b)<<".0000"<<endl; 16 } 17 return 0; 18 }
但这毕竟是奇技淫巧,还是上正解
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 double a[302][302]; 8 int n; 9 int main() 10 { 11 int i,j,now,k,x,T; 12 freopen("circle.in","r",stdin); 13 freopen("circle.out","w",stdout); 14 cin>>T; 15 while (T--) 16 { 17 cin>>n>>x; 18 memset(a,0,sizeof(a)); 19 for (i=0; i<=n-1; i++) 20 { 21 if (i==x) 22 { 23 a[i+1][i+1]=1; 24 a[i+1][n+1]=0; 25 } 26 else 27 { 28 a[i+1][i+1]=1; 29 a[i+1][(i-1+n)%n+1]=a[i+1][(i+1)%n+1]=-0.5; 30 a[i+1][n+1]=1; 31 } 32 } 33 for (i=1; i<=n; i++) 34 { 35 now=i; 36 for (j=i+1; j<=n; j++) 37 if (fabs(a[now][i])<fabs(a[j][i])) 38 now=j; 39 for (j=i; j<=n+1; j++) 40 swap(a[now][j],a[i][j]); 41 for (j=i+1; j<=n+1; j++) 42 a[i][j]/=a[i][i]; 43 a[i][i]=1; 44 for (j=i+1; j<=n; j++) 45 { 46 for (k=i+1; k<=n+1; k++) 47 a[j][k]-=a[i][k]*a[j][i]; 48 a[j][i]=0; 49 } 50 } 51 for (i=n; i>=1; i--) 52 { 53 for (j=i+1; j<=n; j++) 54 { 55 a[i][n+1]-=a[i][j]*a[j][n+1]; 56 a[i][j]=0; 57 } 58 a[i][n+1]/=a[i][i]; 59 a[i][i]=1; 60 } 61 printf("%.4lf\n",a[1][n+1]); 62 } 63 }