最长树链

树形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」试题泛做的更多相关文章

  1. #6164. 「美团 CodeM 初赛 Round A」数列互质-莫队

    #6164. 「美团 CodeM 初赛 Round A」数列互质 思路 : 对这个题来言,莫队可以 n*根号n 离线处理出各个数出现个的次数 ,同时可以得到每个次数出现的次数 , 但是还要处理有多少 ...

  2. loj #6177. 「美团 CodeM 初赛 Round B」送外卖2 状压dp floyd

    LINK:#6177.美团 送外卖2 一道比较传统的状压dp题目. 完成任务 需要知道自己在哪 已经完成的任务集合 自己已经接到的任务集合. 考虑这个dp记录什么 由于存在时间的限制 考虑记录最短时间 ...

  3. 【loj6177】「美团 CodeM 初赛 Round B」送外卖2 Floyd+状压dp

    题目描述 一张$n$个点$m$条边的有向图,通过每条边需要消耗时间,初始为$0$时刻,可以在某个点停留.有$q$个任务,每个任务要求在$l_i$或以后时刻到$s_i$接受任务,并在$r_i$或以前时刻 ...

  4. 「美团 CodeM 初赛 Round A」最长树链

    题目描述 Mr. Walker 最近在研究树,尤其是最长树链问题.现在树中的每个点都有一个值,他想在树中找出最长的链,使得这条链上对应点的值的最大公约数不等于1.请求出这条最长的树链的长度. 输入格式 ...

  5. Loj #6164. 「美团 CodeM 初赛 Round A」数列互质

    link : https://loj.ac/problem/6164 莫队傻题,直接容斥做. #include<bits/stdc++.h> #define maxn 100005 #de ...

  6. 【填坑】loj6159. 「美团 CodeM 初赛 Round A」最长树链

    水一水 枚举各个质数,把是这个数倍数的点留下,跑直径,没了 #include <bits/stdc++.h> using namespace std; int h,t,n,p,q,M,N; ...

  7. LiberOJ#6178. 「美团 CodeM 初赛 Round B」景区路线规划 概率DP

    题意 游乐园被描述成一张 n 个点,m 条边的无向图(无重边,无自环).每个点代表一个娱乐项目,第 i 个娱乐项目需要耗费 ci 分钟的时间,会让小 y 和妹子的开心度分别增加 h1i ,h2i ,他 ...

  8. loj6177 「美团 CodeM 初赛 Round B」送外卖2 最短路+状压dp

    题目传送门 https://loj.ac/problem/6177 题解 一直不知道允不允许这样的情况:取了第一的任务的货物后前往配送的时候,顺路取了第二个货物. 然后发现如果不可以这样的话,那么原题 ...

  9. 「美团 CodeM 资格赛」试题泛做

    LibreOJ真是吼啊! 数码 推个式子,把枚举因数转为枚举倍数.然后就发现它是根号分段的.然后每一段算一下就好了. #include <cstdio> #include <cstr ...

随机推荐

  1. windows 控制台默认为UTF-8显示的方法

    这里需要先了解些内容: CHCP CHCP是MS DOS中的命令,用来显示或设置活动代码页编号的.用法是: CHCP [nnn] 其中nnn指定的是代码页的编号.这个参数是可选的,在命令行下如果不指定 ...

  2. 开发过程遇到的css样式问题记录

    一.移动端 1.部分安卓机圆角border-radius失效,显示为方形状?   background-clip: padding-box; 2.部分安卓机字体图标出现锯齿? 使用iconfont图标 ...

  3. servlet容器,web容器,spring容器,springmvc容器的区别(转)

    web容器中有servlet容器,spring项目部署后存在spring容器和springmvc容器.其中spring控制service层和dao层的bean对象.springmvc容器控制contr ...

  4. c#获取桌面路径和bin文件的路径

    string path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory): 生成的运行bin文件下的路径: ...

  5. js判断一个 object 对象是否为空

    方法一:使用for...in for...in... 遍历属性,为真则为“非空数组”:否则为“空数组” for (var i in obj) { return true  // 如果不为空,则会执行到 ...

  6. 微信小程序onLoad、onShow、onHide、onUnload区别

    onLoad:页面第一次加载时触发,从跳转页面返回时不能触发,可以传递参数 onShow:页面显示或从后台跳回小程序时显示此页面时触发,从跳转页面返回时触发,不能传递参数 onHide:页面隐藏,例如 ...

  7. vue访问本地文件404

    用了vue cli3.0用axios调用本地json数据一直报404,找了半天郁闷,最后发现原因是,vue cli3.0 public 文件夹才是静态资源文件,问题解决,记录一下,以后不再踩坑.

  8. 工作总结 [ActionName("ss123")] 更改路由中Action名称 获取或设置操作的名称

  9. TCP超时与重传

    TCP提供可靠的传输层.它使用的方法之一就是确认从另一端收到的数据.但数据和确认都有可能丢失.TCP通过在发送时设置一个定时器来解决这种问题.如果当定时器溢出时还没收到确认,他就重传数该数据.对任何实 ...

  10. python部署到服务器(1) 一一 搭建环境

    本机环境说明 linux下的CentOS 7, 自带python2.7.5, 使用 python --version 命令查看,因系统需要python2.7.5,因此我们并不卸载,另外安装python ...