Codeforces Round 341 div2
2016-02-03 09:17
417 查看
Codeforces Round 341 div2
题目链接:
通过数:3(一题被叉一题未看懂)
Standing:310/5929
Rating change: 1862-1869
比赛总结:
题目都属于可以理解可以做的范围,原来以为要变色了……
A:
所有数任意选,求最大的和且和为偶数的值。
B:
坐标,发现就是y=x+b和y=-x+b上,所以直接换了个坐标系。
好像有更复杂的写法,然而不想补了
C:
刚开始没看懂题,看懂后秒过了。求相邻一对取数能取到p的倍数的概率,这还用想吗
D:
因为之前写过一个处理这种大数的题,所以得意忘形的开loglog处理就没管了……然而忘记了对数的性质。
笨办法是分类讨论,水办法是long double。
看到一种神做法,把数看成实数,然后排序……贴一下
转侵删
If x > 1, then log(log(x)) is an increasing function, and if x < 1, thenreal(log(log(x))) is a decreasing function, because taking a logarithm of a negative number results in something like this:log( - x) = log( - 1 * x) = log( - 1) + logx = iπ + log(x). (Assuming log(x) is done in base e) Therefore, to compare two numbers by their loglog, you can do something like this:
bool compare (complex x, complex y) {
if (imag(x) == 0 and imag(y) == 0)
return real(x) > real(y);
else if (imag(x) != 0 and imag(y) == 0)
return false;
else if (imag(x) == 0 and imag(y) != 0)
return true;
else if (imag(x) != 0 and imag(y) != 0)
return real(x) < real(y);}
E:
这题改了一天……
题目意思说凑一个b位的数,要求它mod(x)==k。问有几种凑法。
首先按照数位dp思想。设dp[i][j]表示i位余数为j有多少种情况。然后发现这是一个矩阵快速幂,因为dp[i]可以由dp[i-1]得到。
然而那个矩阵怎么表示?因为乘式表示位dp[i-1]*T=dp[i],想到半夜得到的结果是T[i][j]表示当前余数为i、新添加j时得到余数为j的矩阵。T的初始化见代码,解释的意思是刚开始只有0位时,余数不定。然后由于dp[0] = {1,0,0,…0},故输出T[0][k]即可。
题目链接:
通过数:3(一题被叉一题未看懂)
Standing:310/5929
Rating change: 1862-1869
比赛总结:
题目都属于可以理解可以做的范围,原来以为要变色了……
A:
所有数任意选,求最大的和且和为偶数的值。
[code]#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include <string> #include <algorithm> using namespace std; #define LL long long const int MAXN = 100000 + 5; LL a[MAXN]; int main() { int n; while(scanf("%d", &n) != EOF){ int cnt = 0; LL sum = 0; for(int i = 0 ; i < n ; i++){ LL u; scanf("%I64d", &u); if(u % 2 == 1) a[cnt++] = u; sum += u; } if(sum % 2 == 0) printf("%I64d\n", sum); else{ sort(a, a + cnt); printf("%I64d\n", sum - a[0]); } } return 0; }
B:
坐标,发现就是y=x+b和y=-x+b上,所以直接换了个坐标系。
好像有更复杂的写法,然而不想补了
[code]#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <string> #include <algorithm> #include <iostream> using namespace std; #define LL long long const int MAXN = 4000 + 100; int c1[MAXN], c2[MAXN]; int main() { int n; while(scanf("%d", &n) != EOF){ memset(c1, 0, sizeof(c1)); memset(c2, 0, sizeof(c2)); LL ans = 0; for(int i = 0 ; i < n ; i++){ int x, y; scanf("%d%d", &x, &y); int u = x - y + 1000; int v = x + y + 1000; ans += c1[u]; c1[u]++; ans += c2[v]; c2[v]++; } printf("%I64d\n", ans); } return 0; }
C:
刚开始没看懂题,看懂后秒过了。求相邻一对取数能取到p的倍数的概率,这还用想吗
[code]#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <string> #include <algorithm> #include <iostream> using namespace std; const int MAXN = 100000 + 5; int l[MAXN], r[MAXN]; double lv[MAXN]; double dp[MAXN][3]; int n, p; double cal(int i) { return 1 - (1 - lv[i - 1]) * (1 - lv[i]) ; } int main() { while(scanf("%d%d", &n, &p) != EOF){ for(int i = 1 ; i <= n ; i++){ scanf("%d%d", &l[i], &r[i]); int u1 = l[i] / p, v1 = l[i] % p; int u2 = r[i] / p, v2 = r[i] % p; int temp = u2 - u1; if(v1 == 0) temp++; lv[i] = 1.0 * temp / (r[i] - l[i] + 1); } l[0] = l , r[0] = r ; lv[0] = lv ; l[n + 1] = l[1], r[n + 1] = r[1]; lv[n + 1] = lv[1]; // for(int i = 0 ; i <= n + 1 ; i++) printf("lv[%d] = %f\n", i, lv[i]); double ans = 0; for(int i = 1 ; i <= n ; i++){ ans += cal(i) * 2000; // printf("cal[%d] = %f\n", i, cal(i)); } // memset(dp, 0, sizeof(dp)); // for(int i = 1 ; i <= n + 1; i++){ // if(i == 1){ // dp[i][0] = (1 - lv[i]); // dp[i][1] = lv[i]; // } // else{ // dp[i][0] = (1 - lv[i]) * (dp[i - 1][1]); // dp[i][1] = lv[i] * (dp[i - 1][1] + dp[i - 1][0]); // } // printf("dp[%d][0] = %f, dp[%d][1] = %f\n", i, dp[i][0], i, dp[i][1]); // } // double ans = (dp[n + 1][0] + dp[n + 1][1]) * 1000 * n; printf("%.6f\n", ans); } return 0; }
D:
因为之前写过一个处理这种大数的题,所以得意忘形的开loglog处理就没管了……然而忘记了对数的性质。
笨办法是分类讨论,水办法是long double。
看到一种神做法,把数看成实数,然后排序……贴一下
转侵删
If x > 1, then log(log(x)) is an increasing function, and if x < 1, thenreal(log(log(x))) is a decreasing function, because taking a logarithm of a negative number results in something like this:log( - x) = log( - 1 * x) = log( - 1) + logx = iπ + log(x). (Assuming log(x) is done in base e) Therefore, to compare two numbers by their loglog, you can do something like this:
bool compare (complex x, complex y) {
if (imag(x) == 0 and imag(y) == 0)
return real(x) > real(y);
else if (imag(x) != 0 and imag(y) == 0)
return false;
else if (imag(x) == 0 and imag(y) != 0)
return true;
else if (imag(x) != 0 and imag(y) != 0)
return real(x) < real(y);}
[code]#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <algorithm> #include <iostream> #include <string> using namespace std; #define inf (1000000007) double a[20]; double cal1(double x, double y, double z) { double ans; ans = z * log(y) + log(log(x)); // printf("x = %f, y = %f, z = %f\n"); // printf("first part = %f\nsecond part = %f\n", z * log(y), log(log(x))); // system("pause"); // printf("ans = %f\n", ans); return ans; } double cal2(double x, double y, double z) { double ans; ans = log(y) + log(z) + log(log(x)); return ans; } int solve(double x, double y, double z) { for(int i = 1 ; i <= 12 ; i++) a[i] = -inf; if(x <= 1 && y <= 1 && z <= 1){ double xx = 1.0 / x, yy = 1.0 / y, zz = 1.0 / z; if(xx != 1){ a[1] = cal1(xx, y, z); a[2] = cal1(xx, z, y); a[3] = cal2(xx, y, z); a[4] = cal2(xx, z, y); } if(yy != 1){ a[5] = cal1(yy, x, z); a[6] = cal1(yy, z, x); a[7] = cal2(yy, x, z); a[8] = cal2(yy, z, x); } if(zz != 1){ a[9] = cal1(zz, x, y); a[10] = cal1(zz, y, x); a[11] = cal2(zz, x, y); a[12] = cal2(zz, y, x); } int re = 1; double mmax = a[1]; for(int i = 1 ; i <= 12 ; i++){ if(a[i] < mmax) mmax = a[i], re = i; } return re; } else{ if(x > 1){ a[1] = cal1(x, y, z); a[2] = cal1(x, z, y); a[3] = cal2(x, y, z); a[4] = cal2(x, z, y); } if(y > 1){ a[5] = cal1(y, x, z); a[6] = cal1(y, z, x); a[7] = cal2(y, x, z); a[8] = cal2(y, z, x); } if(z > 1){ a[9] = cal1(z, x, y); a[10] = cal1(z, y, x); a[11] = cal2(z, x, y); a[12] = cal2(z, y, x); } } // for(int i = 1 ; i <= 12 ; i++) // printf("%f\n", a[i]); // printf("\n"); int re = 1; double mmax = a[1]; for(int i = 1 ; i <= 12 ; i++){ if(a[i] > mmax) mmax = a[i], re = i; } return re; } int out[5]; void print(int mark) { if(mark == 1) printf("x^y^z\n"); if(mark == 2) printf("x^z^y\n"); if(mark == 3) printf("(x^y)^z\n"); if(mark == 4) printf("(x^z)^y\n"); if(mark == 5) printf("y^x^z\n"); if(mark == 6) printf("y^z^x\n"); if(mark == 7) printf("(y^x)^z\n"); if(mark == 8) printf("(y^z)^x\n"); if(mark == 9) printf("z^x^y\n"); if(mark == 10) printf("z^y^x\n"); if(mark == 11) printf("(z^x)^y\n"); if(mark == 12) printf("(z^y)^x\n"); } int main() { // printf("log(3.4) = %f, loglog(1.1) = %f\n", log(3.4), log(log(1.1))); double x, y, z; while(cin >> x >> y >> z){ // x *= 10, y *= 10, z *= 10; // x *= 1000, y *= 1000, z *= 1000; int mark = solve(x, y, z); print(mark); } // } return 0; }
E:
这题改了一天……
题目意思说凑一个b位的数,要求它mod(x)==k。问有几种凑法。
首先按照数位dp思想。设dp[i][j]表示i位余数为j有多少种情况。然后发现这是一个矩阵快速幂,因为dp[i]可以由dp[i-1]得到。
然而那个矩阵怎么表示?因为乘式表示位dp[i-1]*T=dp[i],想到半夜得到的结果是T[i][j]表示当前余数为i、新添加j时得到余数为j的矩阵。T的初始化见代码,解释的意思是刚开始只有0位时,余数不定。然后由于dp[0] = {1,0,0,…0},故输出T[0][k]即可。
[code]#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <string> #include <algorithm> #include <iostream> using namespace std; #define LL long long #define mod (1000000007) const int MAXN = 100 + 5; struct Matrix { LL a[MAXN][MAXN]; int len; Matrix(){memset(a, 0, sizeof(a));} void init(int _len){ len = _len; for(int i = 0 ; i < len ; i++){ for(int j = 0 ; j < len ; j++){ if(i == j) a[i][j] = 1; else a[i][j] = 0; } } } Matrix operator + (const Matrix &rbs)const{ Matrix res; res.len = len; for(int i = 0 ; i < len ; i++) for(int j = 0 ; j < len ; j++) res.a[i][j] = (a[i][j] + rbs.a[i][j]) % mod; return res; } Matrix operator * (const Matrix &rbs)const{ Matrix res; res.len = len; for(int i = 0 ; i < len ; i++){ for(int k = 0 ; k < len ; k++){ for(int j = 0 ; j < len ; j++) res.a[i][j] = (res.a[i][j] + a[i][k] * rbs.a[k][j]) % mod; } } return res; } void print(){ for(int i = 0 ; i < len ; i++){ for(int j = 0 ; j < len ; j++) printf("%I64d ", a[i][j]); printf("\n"); } } }; Matrix ppow(Matrix u, int b) { Matrix ans; ans.init(u.len); for(int i = b ; i ; i >>= 1){ if(i & 1) ans = (ans * u); u = (u * u); // ans.print(); // printf("\n"); // u.print(); // system("pause"); } return ans; } int n, b, k, x; LL g[MAXN]; LL out[MAXN]; int main() { while(scanf("%d%d%d%d", &n, &b, &k, &x) != EOF){ memset(g, 0, sizeof(g)); int u; while(n--){ scanf("%d", &u); g[u % x]++; } Matrix temp; temp.len = x; for(int i = 0 ; i < x ; i++){ for(int j = 0 ; j < x ; j++){ temp.a[i][(10 * i + j) % x] = g[j]; } } // temp.print(); // system("pause"); // for(int i = 0 ; i < x ; i++){ // for(int j = 0 ; j < x ; j++) printf("%I64d ", temp.a[i][j]); // printf("\n"); // } temp = ppow(temp, b); // temp.print(); // LL ans = 0; // for(int i = 0 ; i < x ; i++) ans = (ans + temp.a[k][i]) % mod; // printf("%I64d\n", ans); // for(int i = 0 ; i < x ; i++){ // for(int j = 0 ; j < x ; j++) printf("%I64d ", temp.a[i][j]); // printf("\n"); // } // memset(out, 0, sizeof(out)); // for(int i = 0 ; i < x ; i++) for(int j = 0 ; j < x ; j++) out[i] = (out[i] + g[j] * temp.a[i][j]) % mod; // for(int i = 0 ; i < x ; i++) printf("%I64d ", out[i]); // printf("\n"); printf("%I64d\n", temp.a[k][0]); } return 0; }
相关文章推荐
- 12.5 管理问题的解决方案
- 【反ajax】webSocket实现实时推送功能
- 天声人語 20160203 新たな脅威「ジカ熱」
- 12.4.1 压缩索引
- 12.4 与应用特点相匹配的解决方案
- cgroup学习(四)——mount hierarchy
- (7)shell数组
- Android 界面设计尺寸规范
- Ubuntu下使用SVN
- cgroup学习(三)——伪文件
- 12.3.1 局部索引
- 欢迎使用CSDN-markdown编辑器
- 12.3 分区索引
- cgroup的学习(一)——what cgroup?
- cgroup学习(二)——cgroup框架结构
- 12.2.1 B-树索引
- iOS 应用架构谈 本地持久化方案
- 原来方法也可以这样使用
- Fortran学习笔记(6)
- 12.2 索引结构类型