VP Educational Codeforces Round 13


A. Johny Likes Numbers

题意:找出比n大的最小的k的倍数。

求出nk的几倍后加一乘k

点击查看代码
void solve() {
    int n, k;
    std::cin >> n >> k;
    std::cout << (n / k + 1) * k << "\n";
}


B. The Same Calendar

题意:给出当前年份,求下一个每天星期数都相等的年份。

首先只有两个年份天数相同才可能,然后考虑枚举,发现365%7=1,366%7=2,那么当是闰年就加2,不是就加1,当这个加出来的数是7的倍数就是答案。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    auto check = [&](int n) -> int {
    	return n % 400 == 0 || (n % 4 == 0 && n % 100 != 0);
    };

    int x = check(n);
    int t = 0;
    do {
    	++ n;

    	if (check(n)) {
    		t += 366;
    	} else {
    		t += 365;
    	}

    } while (t % 7 || check(n) != x);

    std::cout << n << "\n";
}

C. Joty and Chocolate

题意:在[1,n]这些数里,你可以给a的倍数每个加p的价值,给b的倍数每个加q的价值,每个数只能用一次,求最大价值。

显然我们应该让价值大的染更多的色,并且给更多数染色,那么先给a,b的倍数都算一遍,然后减去它们重复的倍数的价值就行。

点击查看代码
void solve() {
    i64 n, a, b, p, q;
    std::cin >> n >> a >> b >> p >> q;
    if (p < q) {
    	std::swap(a, b);
    	std::swap(p, q);
    }

    i64 ans = 0;
    ans += n / a * p + n / b * q - n / (a / std::gcd(a, b) * b) * q;
    std::cout << ans << "\n";
}

D. Iterated Linear Function

题意:一个递归函数:f(x)=Ax+B,g(n,x)=f(g(n1,x))n>0;g(n,x)=x,n=0。求g(n,x)

模拟一下,g(0,x)=x,g(1,x)=Ax+B,g(2,x)=A2x+AB+B,g(3,x)=A3x+A2B+AB+B,那么发现最终x的系数是An,然后后面是i=0n1Ai×B,发现这是一个等比数列,用等比数列求和公式计算即可。

点击查看代码
void solve() {
    i64 A, B, n, x;
    std::cin >> A >> B >> n >> x;
    if (A == 1) {
    	std::cout << x + (Z)n * B << "\n";
    	return;
    }

    //A^n * x + A^n-1 * B + A^n-2 * B.. A^0 * B
    Z ans = power<Z>(A, n) * x + (1 - power<Z>(A, n)) / (Z)(1 - A) * B;
    std::cout << ans << "\n";
}

E. Another Sith Tournament

题意:有n个人要比赛,每场比赛两两对决,第i个人有p[i][j]几率战胜第j个人。你是第一个人,你可以选择第一个上场的人,已经在每场比赛后选一个没上场的人替换失败的人。

n<=18,自然想到状压dp,但状态转移有点说法,如果正着做,记f[s][i]为当前上场过的集合为s,剩下i的获胜概率,发现转移方程好想,但算出来答案不对,因为有些状态的值不好确定,如果集合有过第一个人,但获胜者不是第一个,概率应该为0,但这样就打乱我们的转移过程。
考虑反着来,f[s][i]表示i在擂台上,s集合的人都可以上场,那么倒着来,f[1][0]=1,然后对于每个f[s][i],选一个未上场的j来和i打,就有两种结果,取最大值就可以,状态转移方程为f[s][i]=max(f[s][i],f[s(1<<j)][i]×p[i][j]+f[1(1<<i)][j]×f[j][i])

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector p(n, std::vector<double>(n));
    for (int i = 0; i < n; ++ i) {
    	for (int j = 0; j < n; ++ j) {
    		std::cin >> p[i][j];
    	}
    }

    std::vector f(1 << n, std::vector<double>(n));
    f[1][0] = 1;

    for (int i = 2; i < 1 << n; ++ i) {
    	for (int j = 0; j < n; ++ j) {
    		if (i >> j & 1) {
    			for (int k = 0; k < n; ++ k) {
    				if ((i >> k & 1) && j != k) {
    					f[i][j] = std::max(f[i][j], f[i - (1 << k)][j] * p[j][k] + f[i - (1 << j)][k] * p[k][j]);
    				}
    			}
    		}
    	}
    }

    double ans = 0;
    for (int i = 0; i < n; ++ i) {
    	ans = std::max(ans, f[(1 << n) - 1][i]);
    }

    std::cout << std::fixed << std::setprecision(12);
    std::cout << ans << "\n";
}
posted @   maburb  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示