A:
枚举被分成几块。当分成i块确定时,就可以O(1)求出此时答案。
比如正分有i块,负分就有i+1块,
正分就分成I-1个是1 剩下的都放一个里面;负分的则尽量放平均
- int main() {
- LL n, m;
- while(scanf("%I64d%I64d", &n, &m) != EOF){
- if(m==0){
- printf("%I64d\n", n*n);
- for(int i = 0; i < n; ++i) putchar('o');
- }
- else if(m==1){
- printf("%I64d\n", n*n - 1);
- putchar('x');
- for(int i = 0; i < n; ++i) putchar('o');
- }
- else if(n==0){
- printf("%I64d\n", -m*m);
- for(int i = 0; i < m; ++i) putchar('x');
- }
- else{
- int ii = 1;
- LL ans = -100000000000;
- LL tmp, ave, m1, m2;
- for(int i = 1; i <= min(n, m-1); ++i){
- tmp = (n - i + 1) * (n - i + 1) + i - 1;
- ave = m / (i+1);
- m2 = m - ave * (i+1);
- m1 = i + 1 - m2;
- tmp -= m1*ave*ave + m2*(ave+1)*(ave+1);
- if(tmp > ans){
- ans = tmp;
- ii = i;
- }
- }
- printf("%I64d\n", ans);
- ave = m / (ii+1);
- m2 = m - ave * (ii+1);
- m1 = ii + 1 - m2;
- for(int i = 1; i <= ii; ++i){
- for(int j = 1; j <= ave+(i>m1); ++j) putchar('x');
- for(int j = 1; j <= (i==1 ? n-ii+1 : 1); ++j) putchar('o');
- }
- for(int j = 1; j <= ave+(ii+1>m1); ++j) putchar('x');
- }
- puts("");
- }
- return 0;
- }
B:
当行数和列数的有1数量固定时,那么答案是固定的。
记忆画搜索,dfs.
下面x表示横着有1数量; y表示竖着有1数量; E表示期望
E1 = x * y * (E(x, y) + 1.0) /n/n //表示选择的点是横竖本来就都有1的
E2 = x * (n - y) * (E(x, y + 1) + 1.0)/n/n //表示选择的点横着不影响,影响竖着的多了
E3 = (n - x) * y * (E(x + 1, y) + 1.0)/n/n
E4 = (n - x) * (n - y )* (E(x + 1, y + 1) + 1.0)/n/n
E(x, y) = E1 + E2 + E3 + E4
就得出:
E(x, y) = …… 我就不写了
- const int N = 2005;
-
- double dp[N][N];
- int n, m;
- int visx[N], visy[N];
- double dfs(int nx, int ny){
- if(nx == n && ny == n) return 0;
- if(nx > n || ny > n) return 0;
- if(dp[nx][ny] > -0.001) return dp[nx][ny];
- dp[nx][ny] = nx * ny * 1.0;
- dp[nx][ny] += nx * (n - ny) * (dfs(nx, ny+1) + 1.0);
- dp[nx][ny] += (n - nx) * ny *(dfs(nx+1, ny) + 1.0);
- dp[nx][ny] += (n - nx) * (n - ny) * (dfs(nx+1, ny+1) + 1.0);
- dp[nx][ny] /= 1.0 * n * n - 1.0 * nx * ny;
- return dp[nx][ny];
- }
-
-
- int main(){
- while(scanf("%d%d", &n, &m) != EOF){
- memset(visx, 0, sizeof(visx));
- memset(visy, 0, sizeof(visy));
- while(m--){
- int x, y;
- scanf("%d%d", &x, &y);
- visx[x] = 1;
- visy[y] = 1;
- }
- int numx = 0 , numy = 0;
- for(int i = 1; i <= n; ++i) numx += visx[i];
- for(int i = 1; i <= n; ++i) numy += visy[i];
- memset(dp, -1, sizeof(dp));
- printf("%.10f\n" , dfs(numx, numy));
- }
- return 0;
- }