Problem A modsum

求$\sum\limits_{i=1}^{n} \sum\limits_{j=1 , i \neq j}^{m} (n \ mod \ i)(m \ mod \ j)$

在模$ 19940417 $的意义下计算答案。

对于$100\%$的数据,满足$1 \leq n,m \leq 10^9$

Solution :

由于$n,m$的答案和$m,n$的答案都是一样的,我们不妨令$n\leq m$

一眼想到了整除分块,我们显然可以通过$O(\sqrt{n})$的复杂度求出

$G(n,k) = \sum\limits_{i=1}^{n} (k \ mod \ i)$的值。

我们考虑化简原来的式子,原式$ = \sum\limits_{i=1}^{n} ((\sum\limits_{j=1}^{m} (n\ mod \ i)(m \ mod \ j))- (n \ mod \ i)(m \ mod \ i))$

$ = \sum\limits_{i=1}^n\sum\limits_{j=1}^{m}(n \ mod \ i)(m \ mod \ j) - \sum\limits_{i=1}^{n} (n \ mod \ i)(m \ mod \ i)$

$ = \sum_{i=1}^n\sum_{j=1}^{m}(n \ mod \ i)(m \ mod \ j) -\sum_{i=1}^{n}(n-i\times \left \lfloor \frac{n}{i} \right \rfloor)(m-i\times \left \lfloor \frac{m}{i} \right \rfloor)$

$== \sum_{i=1} ^n (n \ mod \ i)\sum_{i=1}^{m} (m \ mod \ i)- n^2 m + m\sum_{i=1}^{n} i \times \left \lfloor \frac{n}{i} \right \rfloor + n\sum_{i=1}^{n} i \times \left \lfloor \frac{m}{i} \right \rfloor - \sum_{i=1}^{n} \left \lfloor \frac{n}{i} \right \rfloor  \left \lfloor \frac{m}{i} \right \rfloor i^2$

对于$ \sum_{i=1}^{n} \left \lfloor \frac{n}{i} \right \rfloor  \left \lfloor \frac{m}{i} \right \rfloor i^2$的求法可以整除分块,每一次跳最小值来实现。

由于最多是有$2\sqrt{n}$条线,所以复杂度是$O(\sqrt{n})$

注意到$19940417$ 不是质数,然而$\sum_{i=1}^{n} i^2 = \frac{n\times(n+1)\times(2n+1)}{6}$中的$6$和它是互质的,所以可以简单的for循环求逆元即可。

# include <bits/stdc++.h>
# define int long long
using namespace std;
const int mo=;
int inv6=;
int inv2=;
int mul(int x,int n)
{
int ans=;
while (n) {
if (n&) ans=(ans+x)%mo;
n>>=;
x=(x+x)%mo;
}
return ans%mo;
}
int fun(int l,int r){
l--;
return (((mul(mul(r,r+),*r+)*inv6)%mo-(mul(mul(l,l+),*l+)*inv6)%mo)%mo+mo)%mo;
}
int calc1(int n,int m)
{
int ret=;
for (int l=,r1,r2,r;l<=n;l=r+) {
if (n/l!=) r1=min(n/(n/l),n); else r1=n;
if (m/l!=) r2=min(m/(m/l),n); else r2=m;
r=min(r1,r2);
ret=(ret + mul(mul((n/l),(m/l)),fun(l,r)))%mo;
}
return ret%mo;
}
int calc(int n,int k) {
int ret=;
for (int l=,r;l<=n;l=r+) {
if (k/l!=) r=min(k/(k/l),n);
else r=n;
ret=(ret + mul(mul(mul(k/l,(r-l+)),(l+r)),inv2))%mo;
}
return ret%mo;
}
int G(int n,int k) { return ((mul(n,k)-calc(n,k))%mo+mo)%mo;}
signed main()
{
int n,m; scanf("%lld%lld",&n,&m);
if (n>m) swap(n,m);
int ans=mul(G(n,n),G(m,m))-mul(mul(n,n),m)+mul(m,calc(n,n))+mul(n,calc(n,m))-calc1(n,m);
printf("%lld\n",(ans%mo+mo)%mo);
return ;
}

A.cpp

Problem B queue

给出一棵多叉树,求关于所有节点的排列数,要求:

  1. 每棵子树的根节点先于这棵子树的其他节点出现。

  2. 和一个节点直接相连的节点必须依次出现但可不连续。

在$mod \ 10007$ 意义下询问排列数。
对于$100\%$的数据$1 \leq n\leq 10^3$

Solution :

可以将多叉树转化为二叉树,答案显然不变。

 一种显然的转化方法就是将每个点的儿子按照一条链连接下去,这样一定保证是二叉树。

设$f[u]$表示将$u$的子树排列的可行数目,显然从$f[l_{son}]$和$f[r_{son}]$转移过来。

显然,$f[u] = f[l_{son}] \times f[r_{son}] \times C_{size[l_{son}]+size[r_{son}]}^{size[l_{son}]}$

其中合并的贡献就是在$size[l_{son}]+size[r_{son}]$个位置上放$size[l_{son}]$个数字的方案数(顺序没有关系)。

复杂度是 预处理组合数的复杂度是$O(n^2)$  

# include <bits/stdc++.h>
# define int long long
using namespace std;
const int N=;
const int mo=;
vector<int>E[N];
int c[N][N],n,size[N],f[N];
int C(int n,int m){return c[n][m];}
void dfs(int u)
{
if (E[u].size()==) {
size[u]=; f[u]=;
return;
}
if (E[u].size()==) {
dfs(E[u][]); size[u]=size[E[u][]]+;
f[u]=f[E[u][]];
}
if (E[u].size()==) {
dfs(E[u][]); dfs(E[u][]);
size[u]=size[E[u][]]+size[E[u][]]+;
f[u]=f[E[u][]]*f[E[u][]]%mo*C(size[E[u][]]+size[E[u][]],size[E[u][]])%mo;
}
}
signed main()
{
c[][]=;
for (int i=;i<=;i++) {
c[i][]=c[i][i]=;
for (int j=;j<i;j++)
c[i][j]=(c[i-][j-]+c[i-][j])%mo;
}
int T; scanf("%lld",&T);
while (T--) {
scanf("%lld",&n);
for (int i=;i<=n;i++) f[i]=;
for (int i=;i<=n;i++) E[i].clear();
for (int i=;i<=n;i++) {
int k; scanf("%lld",&k);
int nowf=i;
for (int j=;j<=k;j++) {
int x; scanf("%lld",&x);
E[nowf].push_back(x);
nowf=x;
}
}
dfs();
printf("%lld\n",f[]);
}
return ;
}

B.cpp

Problem C city

 每个点的点权是$w[i]$,经过一条边的代价是$|w[u] - w[v]|$.

定义一条路径$val_S$的代价是路径经过边的最大代价,即$val_S = max\{w[Edge] (Edge \in S)\}$

设需要的能量为$D$,设两点存在“正常的关系”为:至少有两条不重叠的路径$S,T$使得$D \leq val_S , D \leq val_T$

询问$u,v$是否是可能是正常的关系,如果是,输出所需最少能量$D$,否则输出"infinitely"

对于$100\%$的数据$n,m,q \leq 5\times 10^5 $

Solution :

  建出最小生成树,这样树边都不是可行边,从小到大拿非树边取更新答案。

  由于非树边$(u,v)$添加上后会形成环,就存在边双了,这个环上的所有点的答案就是这条边的权值。

  我们只需要将这些点的答案用这条边的权值更新掉即可。

  由于边权排序了,所以后面的边来更新一定不是最优的,所以我们只需要用一个并查集将树上路径折叠掉即可。

  询问的时候直接求一遍倍增lca即可。

  复杂度是$O(n \ log_2 \ n)$

# include<bits/stdc++.h>
using namespace std;
const int N=1e5+,M=5e5+;
struct rec{ int pre,to,w;}a[N<<];
struct A{ int u,v,w;}Edge[M];
bool cmp(A a,A b){return a.w<b.w;}
int tot,n,m,q,val[N],g[N][],d[N][],f[N],head[N],dep[N];
bool inTree[M];
void adde(int u,int v)
{
a[++tot].pre=head[u];
a[tot].to=v;
head[u]=tot;
}
int father(int x)
{
if (f[x]==x) return x;
return f[x]=father(f[x]);
}
void kruskal()
{
for (int i=;i<=n;i++) f[i]=i;
sort(Edge+,Edge++m,cmp);
for (int i=;i<=m;i++) {
int fx=father(Edge[i].u),fy=father(Edge[i].v);
if (fx == fy) continue;
f[fy] = fx;
adde(Edge[i].u,Edge[i].v);
adde(Edge[i].v,Edge[i].u);
inTree[i]=;
}
}
void dfs(int u,int fa)
{
g[u][]=fa; dep[u]=dep[fa]+;
for (int i=head[u];i;i=a[i].pre) {
int v=a[i].to; if (v==fa) continue;
dfs(v,u);
}
}
void init()
{
for (int i=;i<=;i++)
for (int j=;j<=n;j++)
g[j][i]=g[g[j][i-]][i-],
d[j][i]=max(d[j][i-],d[g[j][i-]][i-]);
}
int query(int u,int v){
int ret=;
if (dep[u]<dep[v]) swap(u,v);
for (int i=;i>=;i--)
if (dep[g[u][i]]>=dep[v]) ret=max(ret,d[u][i]),u=g[u][i];
if (u==v) return ret;
for (int i=;i>=;i--) if (g[u][i]!=g[v][i]) {
ret=max(max(ret,d[u][i]),d[v][i]);
u=g[u][i]; v=g[v][i];
}
return max(ret,max(d[u][],d[v][]));
}
int main()
{
// freopen("city.in","r",stdin);
// freopen("city.out","w",stdout);
scanf("%d%d%d",&n,&m,&q);
for (int i=;i<=n;i++) scanf("%d",&val[i]);
for (int i=;i<=m;i++)
scanf("%d%d",&Edge[i].u,&Edge[i].v),Edge[i].w=abs(val[Edge[i].v]-val[Edge[i].u]);
kruskal(); dfs(,);
for (int i=;i<=n;i++) f[i]=i;
for (int i=;i<=m;i++) if (!inTree[i]) {
int fx=father(Edge[i].u),fy=father(Edge[i].v);
while (fx!=fy) {
if (dep[fx]<dep[fy]) swap(fx,fy);
d[fx][]=Edge[i].w; f[fx]=g[fx][]; fx=father(fx);
}
}
init();
while (q--) {
int u,v; scanf("%d%d",&u,&v);
if (father(u)!=father(v)) puts("infinitely");
else printf("%d\n",query(u,v));
}
return ;
}

C.cpp

HGOI20190815 题解的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. NOIP2012 D2T3 疫情控制 题解

    题面 这道题由于问最大值最小,所以很容易想到二分,但怎么验证并且如何实现是这道题的难点: 首先我们考虑,对于一个军队,尽可能的往根节点走(但一定不到)是最优的: 判断一个军队最远走到哪可以树上倍增来实 ...

  2. Codeforces 817+818(A~C)

    (点击题目即可查看原题) 817A Treasure Hunt 题意:给出起点和终点,每次移动只能从 (a,b)移动至(a+x,b+y) , (a+x,b-y) , (a-x,b+y) , (a-x, ...

  3. 从入门到自闭之Python while如何使用

    while 循环 ​ while 条件: ​ 循环体 终止循环的两种办法: 改变条件 break break和continue的用法: break 用法:打破当前循环,(终止当前循环),所处位置在循环 ...

  4. 从入门到自闭之Python序列化

    序列化(背) json :将数据类型转换成字符串(序列化),将字符串装换成原数据类型(反序列),支持dict,list,tuple等,序列后都变成了列表 dumps,loads ------ 用于网络 ...

  5. 协程+IO切换+小爬虫

    from gevent import monkeymonkey.patch_all() import geventimport requests def f1(url): print(f'GET:{u ...

  6. Linux: cp 复制文件、文件夹到文件夹

    参数 a 该选项通常在拷贝目录时使用.它保留链接.文件属性,并递归地拷贝目录,其作用等于dpR选项的组合. d 拷贝时保留链接.    f 删除已经存在的目标文件而不提示.    i 和f选项相反,在 ...

  7. Codeforces 1221C. Perfect Team

    传送门 考虑如何保证限制,首先团队数最大就是 $min(c,m)$ 但是还不够,每个团队还要 $3$ 个人,所以还要和 $(c+m+x)/3$ 再取 $min$ 这样就满足所有限制了 #include ...

  8. Collection<E>接口

    https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html public interface Collection<E ...

  9. C# 面向对象7 命名空间

    命名空间 **namespace(命名空间),用于解决类重名问题,可以看作"类的文件夹" **如果代码和被使用的类在一个namespace则不需要using **在不同命名空间下的 ...

  10. 埋在 MYSQL 数据库应用中的17个关键问题!

    Mysql的使用非常普遍,跟mysql有关的话题也非常多,如性能优化.高可用性.强一致性.安全.备份.集群.横向扩展.纵向扩展.负载均衡.读写分离等.要想掌握其中的精髓,可得花费不少功力,虽然目前流行 ...