「美团 CodeM 初赛 Round A」试题泛做
最长树链
树形DP。我们发现gcd是多少其实并不重要,只要不是1就好了,此外只要有一个公共的质数就好了。计f[i][j]表示i子树内含有j因子的最长链是多少。因为一个数的不同的质因子个数是log级别的,所以转移的复杂度是log方的。所以总共的时间复杂度就是nlog^2n。
#include <cstdio>
#include <vector>
#include <map> #define R register
#define maxn 100010
#define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
bool vis[maxn];
int pr[maxn / ], prcnt, v[maxn];
struct Edge {
Edge *next;
int to;
} *last[maxn], e[maxn << ], *ecnt = e;
inline void link(R int a, R int b)
{
*++ecnt = (Edge) {last[a], b}; last[a] = ecnt;
*++ecnt = (Edge) {last[b], a}; last[b] = ecnt;
}
int p[maxn][], pc[maxn];
int f[maxn][];
int ans;
void dfs(R int x, R int fa)
{
for (R Edge *iter = last[x]; iter; iter = iter -> next)
if (iter -> to != fa)
{
dfs(iter -> to, x);
for (R int i = ; i <= pc[x]; ++i)
{
R int nx = p[x][i];
for (R int j = ; j <= pc[iter -> to]; ++j)
if (p[iter -> to][j] == nx)
{
cmax(ans, f[x][i] + f[iter -> to][j] + );
cmax(f[x][i], f[iter -> to][j]);
}
}
}
for (R int i = ; i <= pc[x]; ++i) ++f[x][i];
}
int main()
{
R int n; scanf("%d", &n);
for (R int i = ; i < maxn; ++i)
{
if (!vis[i]) pr[++prcnt] = i;
for (R int j = ; j <= prcnt && i * pr[j] < maxn; ++j)
{
vis[i * pr[j]] = ;
if (i % pr[j] == ) break;
}
}
for (R int i = ; i < n; ++i)
{
R int a, b; scanf("%d%d", &a, &b);
link(a, b);
}
for (R int i = ; i <= n; ++i)
{
scanf("%d", v + i);
R int temp = v[i];
for (R int j = ; 1ll * pr[j] * pr[j] <= v[i] && temp != ; ++j)
if (temp % pr[j] == )
{
p[i][++pc[i]] = pr[j];
while (temp % pr[j] == ) temp /= pr[j];
}
temp != ? p[i][++pc[i]] = temp : ;
}
dfs(, );
printf("%d\n", ans);
return ;
}
最长树链
二分图染色
校内训练zzx出给我们做的。相当于求两个匹配的集合,使得两个集合的交集为空集。先设f[i]表示左边i个顶点,右边i个顶点的匹配的方案数。这个可以递推来求。然后再容斥一下,枚举交集为S的方案数。然后我们发现之和S的大小有关,所以就可以只枚举集合大小,剩下的用组合数算一算。
#include <cstdio> #define R register
#define maxn 10000010
const int mod = 1e9 + ;
int f[maxn], pw[maxn], inp[maxn];
inline int qpow(R int base, R int power)
{
R int ret = ;
for (; power; power >>= , base = 1ll * base * base % mod)
power & ? ret = 1ll * ret * base % mod : ;
return ret;
}
inline int C(R int n, R int m)
{
return 1ll * pw[n] * inp[n - m] % mod;
}
int main()
{
R int n; scanf("%d", &n);
f[] = ; f[] = ;
for (R int i = ; i <= n; ++i)
f[i] = (2ll * f[i - ] - 1ll * (i - ) * (i - ) % mod * f[i - ] + 2ll * (i - ) * f[i - ]) % mod;
pw[] = ;
for (R int i = ; i <= n; ++i) pw[i] = 1ll * pw[i - ] * i % mod;
inp[n] = qpow(pw[n], mod - );
for (R int i = n; i; --i) inp[i - ] = 1ll * inp[i] * i % mod;
R int ans = ;
for (R int i = , p = ; i <= n; ++i, p = -p)
(ans += (mod + 1ll * p * inp[i] * C(n, i) % mod * C(n, i) % mod * f[n - i] % mod * f[n - i] % mod) % mod) %= mod;
printf("%d\n", ans);
return ;
}
二分图染色
倒水
我一开始想了半天的二分,然后后来发现只要大力分类讨论三种情况就好了。。。T小于温度最小值的,T大于温度最大值的,T在中间的。
最后一种是不成立的(因为最终的温度不可能大于或小于T,又因为T不可能和不等于T的水混合成T,所以不成立)。第一种只要看能否混成最小值就好了,第三种看一下能否混成最大值,如果能的话就把所有的水都用掉。
#include <cstdio> #define R register
#define maxn 100010
#define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
#define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
typedef double db;
int n, T, C, t[maxn], c[maxn];
db left;
inline bool check(R db x)
{
left = C;
for (R int i = ; i <= n; ++i)
if (t[i] != x)
{
if (T == x) return ;
left -= (x * c[i] - (db) t[i] * c[i]) / (T - x);
}
return left >= ;
}
int main()
{
scanf("%d%d%d", &n, &T, &C);
R int maxx = , minn = 0x7fffffff;
for (R int i = ; i <= n; ++i) scanf("%d%d", t + i, c + i), cmax(maxx, t[i]), cmin(minn, t[i]);
if (T <= minn)
{
if (check(minn)) printf("Possible\n%.4lf\n", (db) minn);
else puts("Impossible");
}
else if (T >= maxx)
{
if (!check(maxx)) puts("Impossible");
else
{
R db p1 = (db) T * C, p2 = C;
for (R int i = ; i <= n; ++i) p1 += (db) t[i] * c[i], p2 += c[i];
printf("Possible\n%.4lf\n", p1 / p2);
}
}
else puts("Impossible");
return ;
}
倒水
身体训练
一开始题目看错傻逼了半天QAQ。。。设f[i][j]为第i个人排在第j位所需要的时间,我们发现这种情况出现的概率恰好是n!/(n-1)!=1/n次。所以直接乘上去加起来就好了。
#include <cstdio> #define R register
#define maxn 1010
typedef double db;
db c[maxn], d[maxn];
int main()
{
R int n; R db v, u; scanf("%d%lf%lf", &n, &v, &u);
for (R int i = ; i <= n; ++i) scanf("%lf", c + i);
for (R int i = ; i <= n; ++i) scanf("%lf", d + i);
R db ans = ;
for (R int i = ; i <= n; ++i)
{
for (R int j = ; j < n; ++j)
ans += u / (c[i] - d[i] * j - v);
}
printf("%.3lf\n", ans);
return ;
}
身体训练
合并回文子串
又是zzx校内训练出给我们做的。我们发现最终序列的一个子串在原本的两个序列上对应的是两个区间。所以我们计f[l1][r1][l2][r2]为用A[l1..r1],B[l2..r2]的字符能否组成一个回文串。然后转移的时候只要在端点转移进来。然后这个DP可以用bitset优化,然而我没去写。。。
#include <cstdio>
#include <cstring> #define R register
#define maxn 60
#define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
bool f[maxn][maxn][maxn][maxn];
char A[maxn], B[maxn];
int main()
{
R int T; scanf("%d", &T);
for (; T; --T)
{
scanf("%s%s", A + , B + );
R int n = strlen(A + ), m = strlen(B + );
memset(f, , sizeof (f));
for (R int i = ; i <= n + ; ++i)
for (R int j = ; j <= m + ; ++j)
f[i][i - ][j][j - ] = f[i][i][j][j - ] = f[i][i - ][j][j] = ;
for (R int ln = ; ln <= n; ++ln)
for (R int l1 = , r1 = ln; r1 <= n; ++l1, ++r1)
for (R int lm = ; lm <= m; ++lm)
for (R int l2 = , r2 = lm; r2 <= m; ++l2, ++r2)
{
f[l1][r1][l2][r2] |= f[l1 + ][r1][l2][r2 - ] && A[l1] == B[r2];
f[l1][r1][l2][r2] |= f[l1][r1 - ][l2 + ][r2] && A[r1] == B[l2];
if (ln > ) f[l1][r1][l2][r2] |= A[l1] == A[r1] && f[l1 + ][r1 - ][l2][r2];
if (lm > ) f[l1][r1][l2][r2] |= B[l2] == B[r2] && f[l1][r1][l2 + ][r2 - ];
}
R int ans = ;
for (R int i = ; i <= n; ++i)
for (R int j = i; j <= n; ++j)
for (R int ii = ; ii <= m; ++ii)
for (R int jj = ii; jj <= m; ++jj)
f[i][j][ii][jj] ? cmax(ans, j - i + + jj - ii + ) : ;
printf("%d\n", ans);
}
return ;
}
合并回文子串
数列互质
我会分块莫队(°∀°)ノ!我们注意到一个性质:出现次数超过sqrt(n)的数不会超过sqrt(n)个。我们把这些数成为关键的数,并且可以预处理出它出现次数的前缀和。对于剩下的数出现次数就不会超过sqrt(n)了。我们用莫队把区间内所有非关键数的出现次数处理出来,并且可以处理出 出现次数为i的数的出现次数(好绕口)。。。对于每一个询问的k,先枚举关键的数,看一下出现次数是否满足条件。再枚举一下非关键数里面满足条件的数的个数。时间复杂度q*sqrt(n)*log,那个log是求gcd的。。。一开始直接求gcd被卡T了。后来预处理一下不知怎地就过了。╮( ̄▽ ̄)╭
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring> #define R register
#define maxn 50010
#define maxs 233
int sum[maxs][maxn], cnt[maxn], a[maxn], ans[maxn], idd[maxn], ccnt[maxs], ip[maxs], gg[][];
struct Query {
int l, r, k, id;
inline bool operator < (const Query &that) const {return idd[l] < idd[that.l] || (idd[l] == idd[that.l] && (idd[l] & ? r > that.r : r < that.r));}
} q[maxn];
bool imp[maxn];
int gcd(R int a, R int b)
{
return !b ? a : gcd(b, a % b);
}
int ggcd(R int a, R int b)
{
if (!a || !b) return a + b;
if (a <= && b <= ) return gg[a][b];
return ggcd(b, a % b);
}
inline void add(R int x)
{
if (imp[x]) return ;
cnt[x] ? --ccnt[cnt[x]] : ;
++ccnt[++cnt[x]];
}
inline void del(R int x)
{
if (imp[x]) return ;
--ccnt[cnt[x]--];
cnt[x] ? ++ccnt[cnt[x]] : ;
}
int main()
{
R int n, m, num = , sq; scanf("%d%d", &n, &m); sq = (int) sqrt(n); sq < ? sq = : ;
for (R int i = ; i <= n; ++i) scanf("%d", a + i), ++cnt[a[i]], idd[i] = i / sq;
for (R int i = ; i <= n; ++i)
{
if (cnt[i] >= sq)
{
ip[++num] = i; imp[i] = ;
// printf("i %d\n", i);
for (R int j = ; j <= n; ++j)
sum[num][j] = sum[num][j - ] + (a[j] == i);
}
}
memset(cnt, , sizeof (cnt));
for (R int i = ; i <= m; ++i) scanf("%d%d%d", &q[i].l, &q[i].r, &q[i].k), q[i].id = i;
for (R int i = ; i <= ; ++i)
for (R int j = ; j <= ; ++j)
gg[i][j] = gcd(i, j);
std::sort(q + , q + m + );
R int l = , r = ;
for (R int i = ; i <= m; ++i)
{
while (q[i].r > r) add(a[++r]);
while (q[i].l < l) add(a[--l]);
while (q[i].l > l) del(a[l++]);
while (q[i].r < r) del(a[r--]);
for (R int j = ; j <= sq; ++j)
if (ggcd(j, q[i].k) == ) ans[q[i].id] += ccnt[j];
for (R int j = ; j <= num; ++j)
if (sum[j][q[i].r] - sum[j][q[i].l - ] > && ggcd(sum[j][q[i].r] - sum[j][q[i].l - ], q[i].k) == ) ++ans[q[i].id];
}
for (R int i = ; i <= m; ++i) printf("%d\n", ans[i]);
return ;
}
数列互质
「美团 CodeM 初赛 Round A」试题泛做的更多相关文章
- #6164. 「美团 CodeM 初赛 Round A」数列互质-莫队
#6164. 「美团 CodeM 初赛 Round A」数列互质 思路 : 对这个题来言,莫队可以 n*根号n 离线处理出各个数出现个的次数 ,同时可以得到每个次数出现的次数 , 但是还要处理有多少 ...
- loj #6177. 「美团 CodeM 初赛 Round B」送外卖2 状压dp floyd
LINK:#6177.美团 送外卖2 一道比较传统的状压dp题目. 完成任务 需要知道自己在哪 已经完成的任务集合 自己已经接到的任务集合. 考虑这个dp记录什么 由于存在时间的限制 考虑记录最短时间 ...
- 【loj6177】「美团 CodeM 初赛 Round B」送外卖2 Floyd+状压dp
题目描述 一张$n$个点$m$条边的有向图,通过每条边需要消耗时间,初始为$0$时刻,可以在某个点停留.有$q$个任务,每个任务要求在$l_i$或以后时刻到$s_i$接受任务,并在$r_i$或以前时刻 ...
- 「美团 CodeM 初赛 Round A」最长树链
题目描述 Mr. Walker 最近在研究树,尤其是最长树链问题.现在树中的每个点都有一个值,他想在树中找出最长的链,使得这条链上对应点的值的最大公约数不等于1.请求出这条最长的树链的长度. 输入格式 ...
- Loj #6164. 「美团 CodeM 初赛 Round A」数列互质
link : https://loj.ac/problem/6164 莫队傻题,直接容斥做. #include<bits/stdc++.h> #define maxn 100005 #de ...
- 【填坑】loj6159. 「美团 CodeM 初赛 Round A」最长树链
水一水 枚举各个质数,把是这个数倍数的点留下,跑直径,没了 #include <bits/stdc++.h> using namespace std; int h,t,n,p,q,M,N; ...
- LiberOJ#6178. 「美团 CodeM 初赛 Round B」景区路线规划 概率DP
题意 游乐园被描述成一张 n 个点,m 条边的无向图(无重边,无自环).每个点代表一个娱乐项目,第 i 个娱乐项目需要耗费 ci 分钟的时间,会让小 y 和妹子的开心度分别增加 h1i ,h2i ,他 ...
- loj6177 「美团 CodeM 初赛 Round B」送外卖2 最短路+状压dp
题目传送门 https://loj.ac/problem/6177 题解 一直不知道允不允许这样的情况:取了第一的任务的货物后前往配送的时候,顺路取了第二个货物. 然后发现如果不可以这样的话,那么原题 ...
- 「美团 CodeM 资格赛」试题泛做
LibreOJ真是吼啊! 数码 推个式子,把枚举因数转为枚举倍数.然后就发现它是根号分段的.然后每一段算一下就好了. #include <cstdio> #include <cstr ...
随机推荐
- python中while循环打印星星的四种形状
在控制台连续输出五行*,每一行星号数量一次递增 * ** *** **** ***** #1.定义一个行计数器 row = 1 while row <= 5: #定义一个列计数器 col = 1 ...
- Linux命令-文件管理篇-cat
1.cat 说明 cat 是一个文本文件查看和连接工具.查看一个文件的内容,用cat比较简单,就是cat 后面直接接文件名. 2.使用权限 所有使用者 <!-- more --> 3.ca ...
- Unity Button按钮延迟
1.把下面脚本放到Editor文件夹下,这样脚本继承Button之后,新声明的public变量才能在Inspector面板显示出来. using System.Collections; using S ...
- spark内存管理详解
Spark 作为一个基于内存的分布式计算引擎,其内存管理模块在整个系统中扮演着非常重要的角色.理解 Spark 内存管理的基本原理,有助于更好地开发 Spark 应用程序和进行性能调优.本文旨在梳理出 ...
- Windows+Nginx+Tomcat整合的安装与配置学习笔记
以下全部是nginx在window7下运行的: nginx学习总结: 我的是放在F盘 1.启动:F:\nginx-1.10.2\nginx-1.10.2>start nginx.exe(找到相应 ...
- 如何源码编译安装并控制nginx
安装nginx 注意 Linux操作系统需要2.6及其以上的内核(支持epoll) 使用nginx的必备软件 gcc编辑器 yum -y install gcc gcc-c++ pcre库(支持正则表 ...
- 2019-11-29-解决从旧格式的-csproj-迁移到新格式的-csproj-格式-AssemblyInfo-文件值重复问题...
title author date CreateTime categories 解决从旧格式的 csproj 迁移到新格式的 csproj 格式 AssemblyInfo 文件值重复问题 lindex ...
- 织梦dedecms自定义功能函数(1):调用body中的图片(可多张)
前言 岛主会整理或者开发一系列常用功能函数.所有自定义功能函数都是放在\include\extend.func.php文件里. 这次织梦自定义功能函数功能为:独立提取 body字段中(可以是自定义字段 ...
- Maxwell平滑升级流程
1. 同步配置文件 copy之前的配置文件 2 关掉监控程序 如果有的话 3 kill掉之前的maxwell程序 4 查询已经读取到的position位置,然后重启服务 ...
- 目标检测之车辆行人(darknet版yolov3)
序言 自动驾驶是目前非常有前景的行业,而视觉感知作为自动驾驶中的“眼睛”,有着非常重要的地位和作用.为了能有效地识别到行驶在路上的动态目标,如汽车.行人等,我们需要提前对这些目标的进行训练, ...