2.20 CW 模拟赛 赛时记录
前言#
状态真的不算好, 但是无所谓了, 按照策略做就行了
看题#
给我干哪来了, 这是
#
最好和期望没啥关系
#
不太好想
#
多半是数学题了
总而言之, 不贪跟策略, 数据检验很重要
身体很重要, 秋裤还是穿上吧
#
思路#
每秒在余下的单元中, 以
求第
时间上限为
不难想到
令
什么你说
考虑转移
你发现这个东西假假假, 怎么办, 虽然说改成状态压缩可以过掉
重新设计, 考虑
好吧真的不太会, 没有搞出什么性质, 把部分分打了跑路
#
令
考虑转移
如何统计答案?
枚举
总时间复杂度
#
这种情况怎么做?
不难发现每次删除都是等概率的
所以需要计算
不难发现就是
感觉不太对, 但是先把
实现#
框架#
按照上面实现即可, 但是出题人为什么不给模数, 无敌了
代码#
#include <bits/stdc++.h>
#define int long long
const int MAXN = 1e5 + 20; // 改改改
const int MAXS = (1 << 20) + 1; // 改改改
int n;
int w[MAXN];
/*状态压缩 dp*/
class subtask1 {
private:
struct node { int first, second; };
double f[2][MAXS]; int now = 0, nxt = 1;
std::basic_string<int> size[MAXN];
std::basic_string<node> st[MAXS];
int sigma[MAXS];
void init() {
// for (int S = 0; S < (1 << n); S++) st[S].clear(), sigma[S] = 0;
// for (int i = 0; i <= n; i++) size[i].clear();
for (int S = 0; S < (1 << n); S++) {
size[__builtin_popcount(S)].push_back(S);
for (int i = 1; i <= n; i++) {
if ((S >> (i - 1)) & 1) { sigma[S] += w[i]; continue; }
st[S].push_back({(S | (1 << (i - 1))), i});
}
}
}
public:
void solve() {
init();
double ans = 0;
memset(f, 0, sizeof f);
f[now][(1 << n) - 1] = 1.0;
ans += f[now][(1 << n) - 1] / sigma[(1 << n) - 1] * w[1];
for (int i = 1; i <= n; i++) {
std::swap(now, nxt);
for (int S : size[n - i]) {
for (node Spre : st[S])
f[now][S] += f[nxt][Spre.first] / sigma[Spre.first] * w[Spre.second];
if (S & 1) ans += f[now][S] * (i + 1) / sigma[S] * w[1];
}
}
printf("%.10f", ans);
}
} sub1;
/*ai = 1*/
class subtask3 {
private:
public:
void solve() {
double ans = 0;
for (int i = 1; i <= n; i++) ans += i * 1.0 / n;
printf("%.10f", ans);
}
} sub3;
signed main()
{
scanf("%lld", &n);
for (int i = 1; i <= n; i++) scanf("%lld", &w[i]);
if (n <= 20) sub1.solve();
else sub3.solve();
return 0;
}
#
时间分配有一点问题, 先看这个, 避免上面代码太难打影响心态
还好只有
思路#
先考虑部分分, 因为时间的问题
考虑
不难发现转移
令
然后就是典中典
可以乱搞出
实现#
框架#
首先枚举
代码#
#include <bits/stdc++.h>
#define int long long
const int MAXN = 1e3 + 20; // 改改改
int n, m, k;
int base[MAXN], w[MAXN];
int ans = 0x3f3f3f3f;
bool check(int x) {
int sum = 0, tmp = 0;
for (int i = 1; i <= n; i++) {
if (w[i] > x) return false;
sum += w[i]; if (sum > x) tmp++, sum = w[i];
}
return (tmp + 1) <= k;
}
int solve(int x) {
/*处理当前 a*/ for (int i = 1; i <= n; i++) w[i] = ((base[i] + x) >= m ? base[i] + x - m : base[i] + x);
int left = 0, right = n * m + 1, mid, res = 0x3f3f3f3f;
while (left < right) {
mid = left + (right - left) / 2;
if (check(mid)) res = mid, right = mid;
else left = mid + 1;
}
return res;
}
signed main()
{
scanf("%lld %lld %lld", &n, &m, &k);
for (int i = 1; i <= n; i++) scanf("%lld", &base[i]);
for (int x = 0; x < m; x++) ans = std::min(ans, solve(x));
printf("%lld", ans);
return 0;
}
#
那我问你, 我这样子打得完代码就有鬼了谢谢 上帝/一个高尚无比美丽动人温文尔雅的名字 帮我把鬼打掉了, 请您帮我把挂分也打掉吧
虽然说这样不太好, 但是这场先这样, 节奏保持
思路#
再来一档到达大众分, 但是我感觉以我的数学水平不太可能
好的没思路, 确实不太会, 先开始打, 最后过来干这个
好好好, 上帝啊, 让我再拼一档分吧
算了 上帝/一个高尚无比美丽动人温文尔雅的名字 你别帮了, 我不要在这个事上掉功德, 但是很感谢你帮我打完代码, 谢谢谢谢谢
一个合法的子集需要满足
- 集内数互质
- 集内出现的质数集合之积等于
对
不对, 会不会有其他质数集合之积也等于
所以我们对于集合中的每一个数, 可以拼给他一些质因数, 最多只有
那么显然可以进行一个状态压缩
遗憾, 没搞出来
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】