http://acm.zznu.edu.cn/problem.php?id=1964
题目描述
输入
输出
样例输入
2
2 1
0 1
1 0
3 1
0 1 1
1 0 1
1 1 0
样例输出
0.500
1.125
提示
之前想了一个公式 就是0.5*pow(0.5,k)*C(k,n);
k是至少认识k个人 n是认识n个人
后来队友都把所有的东西都写出来了我才去验证第二个测试数据 发现是错的 当时真的想自己从五楼上跳下来
正确的公式应该是
for(i=k;i<=n;i++)
{
ans+=0.5*pow(0.5,n)*C(i,n);
}
现在想想真是很有道理啊
当时为啥就是蒙蔽呢
#include <iostream> #include <cstring> #include <algorithm> #include <queue> #include <cstdio> #include <cstdlib> #include <cctype> #include <cmath> using namespace std; int num[50]; int x1[50]; int x2[50]; int s[50][50]; void Init(int n) { memset(s, 0, sizeof(s)); for(int i=1; i<=n; i++) { int x=i; for(int j=2; j<=i; j++) { if(x%j==0) { s[i][j]++; x/=j; j--; } } } } long long c(int n, int k) { memset(x1, 0, sizeof(x1)); memset(x2, 0, sizeof(x2)); for(int i=2; i<=k; i++) { for(int j=2; j<=i; j++) { x1[j] += s[i][j]; } } for(int i=n-k+1; i<=n; i++) { for(int j=2; j<=i; j++) { x2[j] += s[i][j]; } } for(int i=2; i<=30; i++) { x2[i]-=x1[i]; } long long ans=1; for(int i=2; i<=30; i++) { for(int j=1; j<=x2[i];j++) { ans*=i; } } return ans; } double solve(int n, int k) { double ans=0; for(int i=k;i<=n;i++) { ans += 0.5*c(n, i)*pow(0.5, n); } return ans; } int main() { int t; int n, k; int x; scanf("%d", &t); Init(30); while(t--) { scanf("%d%d", &n, &k); for(int i=1; i<=n; i++) { int sum1=0; for(int j=1; j<=n; j++) { scanf("%d", &x); if(x==1) sum1++; } num[i]=sum1; } double ans=0; for(int i=1; i<=n; i++) { if(num[i]>=k) { ans+=solve(num[i],k); } } printf("%.3lf ", ans); } return 0; }