前两题A得还挺快,终于分数又涨了一些。。。第三题求出了全部连通集的个数,才发现让求的是全部连通集的大小之和,怎么求大小之和还没想到。ios
1001 DZY Loves Balls 这道题让求出A大于B的几率,可是题目自己好像和几率关系不大,我见过让求指望之类的几率题目,好像都比这个难一些。 一共N个球,取两个,一共的取法是N * (N-1),这里是把值相同的球也看作不一样来想。 求A大于B的状况的种类,咱们能够对这N个值作一个筒排序,从小到大扫描,就能在线性复杂度内求出每一个值的球,比它小的有多少个球,累加这些值就好。spa
#include <cstdio> #include <cstring> #include <iostream> using namespace std; int s[320]; int main() { int t; cin >> t; while(t--) { memset(s, 0, sizeof(s)); int n, a; scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%d", &a); s[a]++; } int presum = 0, p = 0; for(int i = 1; i <= 300; i++) { if(s[i]) p += s[i] * presum; presum += s[i]; } int q = n*(n-1); double ans = (double)p / q; printf("%.6f\n", ans); } return 0; }
1002 DZY Loves Partition 把n分解成k个不一样的数的和,求这k个不一样的数的最大乘积是多少。 若是n小于1到k的累和((1+k) * k / 2),那么确定是无解的。code
若是n大于等于k,咱们能够将n想象成从1加到k再加剩余的部分(n-sum(1,k)),咱们只要把剩余的值想办法加到1到k的一些数中,知足最大乘积最大就好。排序
好比n = 30,k = 7: 1 + 2 + 3 + 4 + 5 + 6 + 7 这不够n,还差2,咱们将2加到某些数上就好。 咱们将后2个数向后移一位是最划得来的,由于1到5不能移动(加2也不会超过7,这样会重复),6+2=8和7+1=8且6+1=7是同样的。ci
其实就是一个贪心策略,咱们总让靠右边的数优先加上1(即向右移动),再证实若是左边的数加上某值获得的结果不会比先前的策略好。string
#include <cstdio> #include <iostream> using namespace std; typedef long long lint; const int mod = 1000000007; int main() { int T; cin >> T; while(T--) { lint n, k; cin >> n >> k; lint l = ((1 + k) * k) / 2; if(n < l) { printf("-1\n"); continue; } lint a = 1, b = k; lint res = n - l; a += (res / k); b += (res / k); res %= k; lint ans = 1; lint o = b; while(o >= a) { if(res) { ans *= (o+1); res--; } else { ans *= o; } ans %= mod; o--; } cout << ans << endl; } return 0; }
代码很简单,注意到若是n-sum(1, k)剩下的值很大的话能够除以n,获得的商加到每一个数上,这样咱们只须要记录k个值的两个端点就好。it