陆续的把最近几场比赛写一写,怕不写又忘了,在补一补没做的题。
A - Alien's Organ ZOJ - 3696 (泊松定理)
刚学过去几天,打比赛时就忘了,被欣姐一顿鄙视,嘤嘤嘤
公式题直接贴代码吧:
#include<bits/stdc++.h>
using namespace std;
int t, n;
double f;
double qf(int k)
{
if(k == 0) return 1;
return k *(qf(k - 1));
}
double get(int k)
{
return pow(f, k) / qf(k);
}
int main()
{
scanf("%d", &t);
while(t--)
{
scanf("%d%lf", &n, &f);
double ans = pow(exp(1), -f);
double sum = 1;
for(int i = 1; i <= n; i++)
sum += get(i);
sum *= ans;
printf("%.3lf\n", sum);
}
return 0;
}
D - Dakar Rally ZOJ - 3699(贪心)
题意:开车行驶,油箱容积一定,只能在特定的点加油,然后让你找到最省钱的加油方式。
1.如果某条路线用的油大于了油箱容积,则不合题意。
2.如果可以找到加油点更便宜或者不用加满就可以到终点的就只需加到所需容积。
3.如果不能则加满。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100005;
int T, m, v, mil, c, a[maxn], p[maxn];
int main()
{
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &m, &v);
int flag = 0;
for(int i = 0; i < m; i++)
{
scanf("%d%d%d", &mil, &c, &p[i]);
a[i] = mil * c;
if(a[i] > v) flag = 1; // 油箱容积不满足
}
if(flag) printf("Impossible\n");
else
{
int i, j;
long long ans, res, t1;
res = ans = 0; i = j = 0;
while(i < m) // 是否到达终点
{
j = i + 1, t1 = a[i];
while(j < m && p[i] <= p[j] && v - t1 >= a[j]) // 看是否有更便宜的下个地点
{
t1 += a[j];
j++;
}
if(j >= m || p[j] < p[i]) // 到终点或者到达更偏的点
{
if(res >= t1) res -= t1;
else
{
ans = ans + (long long)(t1 - res) * p[i];
res = 0;
}
i = j;
}
else // 油箱加满
{
ans = ans + (long long)(v - res) * p[i];
res = v - a[i];
i++;
}
}
printf("%lld\n", ans);
}
}
return 0;
}
G - Gibonacci number ZOJ - 3702(公式推导)
简单的公式推到题,推一推系数项好像可以跟斐波那契数列联系上,但我用了更加朴素的方法,直接记录了常数项和系数项。打表求出。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000100;
int t, i, G, j;
pair<long long, long long> P[maxn];
void init()
{
P[0].first = 0, P[0].second = 1;
P[1].first = 1, P[1].second = 0;
for(int i = 2; i < maxn; i++)
{
P[i].first = P[i - 1].first + P[i - 2].first;
P[i].second = P[i - 1].second + P[i - 2].second;
}
}
int main()
{
init();
scanf("%d", &t);
while(t--)
{
scanf("%d%d%d", &i, &G, &j);
long long re;
re = (G - P[i].second) / P[i].first;
if(re < 1 || re * P[i].first + P[i].second != G)
{
printf("-1\n");
}
else
{
printf("%lld\n", P[j].first * re + P[j].second);
}
}
return 0;
}
H - Happy Programming Contest ZOJ - 3703(01背包+记录路径)
题意:一男生带妹打比赛。然后每道题都有让妹子的最大开心值不同,然后需要在得到最大的妹子开心值的前提下,保证做题量尽量的多且罚时尽量的少。
和普通的01背包不同的一点是这道题要进行路径的记录。对于路径的记录则是要另开一个数组进行记录,如果在dp过程中路径发生了改变,则进行一次记录,最后在查找的时候再进行一遍回溯就可以了。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1010;
int T, t1, n, t[maxn], v[maxn], dp[maxn];
int num[maxn], book[maxn][maxn];
int main()
{
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &t1, &n);
for(int i = 1; i <= n; i++) scanf("%d", &t[i]);
for(int i = 1; i <= n; i++) scanf("%d", &v[i]);
memset(dp, 0, sizeof(dp));
memset(book, 0, sizeof(book));
for(int i = 1; i <= n; i++)
for(int j = t1; j >= t[i]; j--)
{
if(dp[j] < dp[j - t[i]] + v[i])
{
dp[j] = dp[j - t[i]] + v[i];
book[i][j] = 1;
}
}
int j = t1, k = 0, sum = 0, num1 = 0;
for(int i = n; i >= 1; i--)
{
if(book[i][j]){
num[++k] = t[i];
j -= t[i];
}
}
sort(num + 1, num + k + 1);
for(int i = 1; i <= k; i++)
{
num1 += num[i];
sum = sum + num1;
}
printf("%d %d %d\n", dp[t1], k, sum);
}
return 0;
}