Hdu 5112-5122
A 签到c语言级题目 排序求最大差 唯一wa点求绝对值 样例里还体现了...现场赛应该10-15分钟内ac的题目
#include<cstdio>
#include<algorithm>
using namespace std;
struct q { int t, x; }a[10005];
int cmp(q x, q y)
{
return x.t < y.t;
}
int main()
{
int i, n, ca = 1;
double ans;
scanf("%*d");
while (~scanf("%d", &n))
{
for (i = 0; i < n; i++)
scanf("%d%d", &a[i].t, &a[i].x);
sort(a, a + n, cmp), ans = 0;
for (i = 1; i < n; i++)
ans = max(ans, abs(1.*(a[i].x - a[i - 1].x) / (a[i].t - a[i - 1].t)));
printf("Case #%d: %.2lf\n",ca++, ans);
}
}
K没有算法的简单题
每个元素只能往右移动 最少移动次数就是每次找最大的 如果它不在最右就移动到最右
O(n)模拟一下就好
现场应该二三十分钟做出这题吧
#include<cstdio>
int a[1000005], i, n, ca = 1, ans, z;
int main()
{
scanf("%*d");
while (~scanf("%d", &n))
{
for (i = 1; i <= n; i++)
scanf("%d", a + i);
ans = 0, z = n;
for (i = n; i > 0; i--)
if (a[z] != i)
ans++;
else
while (a[z] >= i)
z--;
printf("Case #%d: %d\n",ca++, ans);
}
}
H 终于出现了算法题目..
给出包含n个数的集合 求集合的子集的异或和大于m的个数 n<=40
子集是2^n个 我一直往np问题优化想去了...
简单的做法是模板背包问题 把+换成^就好 但注意+是单调的^后值可能大可能小 不能只用1个1维数组 滚动数组或者40*1e5的数组都可以 复杂度 40*1e5
题解的意思是高斯消元或trie树优化np问题 都有点难..
现场30分钟能做出就不错了...
#include<cstdio>
#include<cstring>
int a[44], dp[44][(1 << 20) + 5], i, j, n, m, ca = 1;
long long ans;
int main()
{
scanf("%*d");
while (~scanf("%d%d", &n, &m))
{
for (i = 1; i <= n; i++)
scanf("%d", a + i);
memset(dp, 0, sizeof(dp)), dp[0][0] = 1;
for (i = 1; i <= n; i++)
{
for (j = (1 << 20) - 1; j >= 0; j--)
dp[i][j] = dp[i - 1][j];
for (j = (1 << 20) - 1; j >= 0; j--)
dp[i][j^a[i]] += dp[i - 1][j];
}
for (i = m, ans = 0; i < (1 << 20); i++)
ans += dp[n][i];
printf("Case #%d: %lld\n", ca++, ans);
}
}
I 计算几何 求2圆环面积交
容斥定理+圆面积交模板很快能过 自己推模板有点麻烦..
S = A大B大 - A大B小 - A小B大 + A小B小
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const double eps = 1e-8;
const double PI = acos(-1.0);
struct Point
{
double x, y;
Point() {}
Point(double _x, double _y)
{
x = _x; y = _y;
}
Point operator -(const Point &b) const
{
return Point(x - b.x, y - b.y);
}
double operator ^ (const Point &b) const
{
return x*b.y - y*b.x;
}
double operator * (const Point &b) const
{
return x*b.x + y*b.y;
}
void transXY(double B)
{
double tx = x, ty = y;
x = tx* cos(B) - ty*sin(B);
y = tx* sin(B) + ty*cos(B);
}
};
double dist(Point a, Point b)
{
return sqrt((a - b)*(a - b));
}
double Ac(Point c1, double r1, Point c2, double r2)
{
double d = dist(c1, c2);
if (r1 + r2 < d + eps) return 0;
if (d < fabs(r1 - r2) + eps)
{
double r = min(r1, r2);
return PI*r*r;
}
double x = (d*d + r1*r1 - r2*r2) / (2 * d), t1 = acos(x / r1), t2 = acos((d - x) / r2);
return r1*r1*t1 + r2*r2*t2 - d*r1*sin(t1);
}
int main()
{
int ca = 1;
Point c1, c2;
double ans, r, R, x1, y1, x2, y2;
scanf("%*d");
while (~scanf("%lf%lf%lf%lf%lf%lf", &r, &R, &x1, &y1, &x2, &y2))
{
c1.x = x1, c1.y = y1, c2.x = x2, c2.y = y2;
ans = Ac(c1, R, c2, R) - Ac(c1, R, c2, r) - Ac(c1, r, c2, R) + Ac(c1, r, c2, r);
printf("Case #%d: %.6lf\n", ca++, ans);
}
}
到这就是做得快有可能得铜牌了..大概是模板充足简单题写的快就有牌
D 区间动态规划
题意很有趣
显然第一排的值一定会计算 所以不用存 记录他们的和就好 主要是第二排的操作
然而答案就是一个等式
dp[i][j]=min(dp[i][k-1]+dp[k+1][j]+a[i-1]+a[j+1]) 其中i<k<j
dp[i][j]表示消灭[i,j]的所有敌人且不消灭任何其他敌人所需的代价 k表示区间留下的最后一个敌人 显然攻击它的代价由区间以左和右的敌人贡献 枚举所有区间和k 复杂度O(n^3)
感觉dp有点递归的意思 找到一个微小的正确的关系 然后一个一个推到全局就一定是正确的 不用太在意中间的过程 电脑会自动完成的..
所以把那个式子翻译成c语言 记忆化搜索一下 果然就过了..
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[222], n, m, ca = 1, ans, dp[222][222];
int dfs(int i, int j)
{
if (dp[i][j] != -1) return dp[i][j];
if (i > j) return 0;
int mi = 1 << 28;
for (int k = i; k <= j; k++)
mi = min(mi, dfs(i, k - 1) + dfs(k + 1, j) + a[i - 1] + a[j + 1]);
dp[i][j] = mi;
return mi;
}
int main()
{
scanf("%*d");
while (~scanf("%d", &n))
{
memset(dp, -1, sizeof(dp)), memset(a, 0, sizeof(a)), ans = 0;
for (int i = 0; i < n; i++)
scanf("%d", &m), ans += m;
for (int i = 1; i <= n; i++)
scanf("%d", a + i);
printf("Case #%d: %d\n", ca++, ans + dfs(1, n));
}
}
这题就是稳铜牌水平 写得快还有银牌 但这样的题不一能很快想到等式关系..
B 很有趣的智力题
给出n*m个格子和n*m个颜色(可能相同) 求是否有相邻颜色不同的铺满格子的方法 有的话输出任意一种 n,m<=5
范围很小直接dfs是可以的 但银牌题显然不会这么轻易..开始写了很zz的代码 改来改去加了剪枝也蜜汁没过
核心是 颜色最多的如果大于剩余格子的一半 则不可能铺满
重写一遍加上这一句剪枝就能过
#include<cstring>
#include<cstdio>
int a[8][8], s[29], n, m, k, f;
void dfs(int x, int y)
{
if (x == n + 1) f = 1;
if (f) return;
int xx, yy, te = n*m - (x - 1)*m - y + 1;
for (int i = 1; i <= k; i++)
if (s[i] > (te + 1) / 2) return;
yy = y + 1, xx = x;
if (yy > m) yy = 1, xx++;
for (int i = 1; i <= k; i++)
if (s[i] > 0 && a[x - 1][y] != i&&a[x][y - 1] != i)
{
s[i]--, a[x][y] = i;
dfs(xx, yy);
if (f) break;
s[i]++, a[x][y] = 0;
}
}
int main()
{
int ca = 1, i, j;
scanf("%*d");
while (~scanf("%d%d%d", &n, &m, &k))
{
memset(a, 0, sizeof(a)), memset(s, 0, sizeof(s));
for (i = 1; i <= k; i++)
scanf("%d", s + i);
f = 0, dfs(1, 1);
printf("Case #%d:\n%s\n", ca++, f ? "YES" : "NO");
if (f)
for (i = 1; i <= n; i++)
{
printf("%d", a[i][1]);
for (j = 2; j <= m; j++)
printf(" %d", a[i][j]);
puts("");
}
}
}
另一种神奇的方法是根据那句话构造 只要一开始最多的颜色不大于(n*m+1)/2 就一定存在方案 但直接O(n*m)构造有点麻烦 特判情况太多..(或者没想到合适的构造方法)
做出上面所有就是稳银牌 多做任意一道其他题就稳金牌
F 概率
给n个灯m个开关 每个开关控制一系列灯 每个开关有0.5的概率开 x为最后亮灯的个数 求E(x^3)*2^m%(1e9+7)
数学+dp+状态压缩 算法倒没什么新奇的..
首先2^m是计算式子的分母 正好抵消掉 只考虑E(x^3)
考虑x是xi的和(i=1..n 0表示灭1表示亮)
x^3=(xi的和)* (xi的和)*(xi的和)=xi*xj*xk的和 1<=i,j,k<=n
所以只用要能求出xijk都为1时的E(xi*xj*xk) 然后三重循环ijk求和就好
能想到这就没什么问题了 状态压缩3个灯的状态和每个开关对灯的操作 和H一模一样的背包 依然是亦或(亦或正好和开灯关灯的模拟步骤完全一样)
总复杂度O(n^3*m) 前面有背包空间的常数2^3 再乘以循环里的常数4(memset和memcpy) 算下来正好是2亿 3秒时限刚好
#include<cstdio>
#include<cstring>
#define mm 1000000007
int n, m, a[55][55];
long long dp[55][9], ans;
int main()
{
int i, j, k, ii, jj, te, x, ca = 1;
scanf("%*d");
while (~scanf("%d%d", &n, &m))
{
memset(a, 0, sizeof(a)), memset(dp, 0, sizeof(dp)), ans = 0;
for (i = 1; i <= m; i++)
{
scanf("%d", &k);
while (k--&&scanf("%d", &x))
a[i][x] = 1;
}
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
for (k = 1; k <= n; k++)
{
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for (ii = 1; ii <= m; ii++)
{
te = a[ii][i] * 4 + a[ii][j] * 2 + a[ii][k];
memcpy(dp[ii], dp[ii - 1], sizeof(dp[ii]));
for (jj = 0; jj < 8; jj++)
dp[ii][jj^te] = (dp[ii][jj^te] + dp[ii - 1][jj]) % mm;
}
ans = (ans + dp[m][7]) % mm;
}
printf("Case #%d: %lld\n", ca++, ans);
}
}
虽然是金牌难度的题但算法只涉及背包dp 数学分析那块有点难..
其他的题就难了..看文字题解也一时半会写不出