【洛谷】xht模拟赛 题解
前言
大家期待已久并没有的题解终于来啦~
这次的T1和HAOI2016撞题了...深表歉意...表示自己真的不知情...
天下的水题总是水得相似,神题各有各的神法。——《安娜·卡列妮娜》
出题的过程:@PhoenixEclipse @xht13127提供了一些想法,我负责写标程,对拍,造数据...然后 @SakuraDance帮我验了题。感谢上述,以及其他几位dalao的资辞。
题解
T1
和HAOI2016撞车 http://www.lydsy.com/JudgeOnline/problem.php?id=4562
30分做法:直接爆搜,注意取模。
100分做法:topo排序然后简单dp,或者直接爆搜加个记忆化...(如果是记忆化,记得不要用0来表示未访问的点QwQ)
T2
wyw神犇提出了一种\(O(\sqrt N)\)的做法,太神啦!详见:http://blog.csdn.net/FSAHFGSADHSAKNDAS/article/details/60475362
一道披着几何外衣的数学题~
问题可以转化为,对 \(a\le i\le b\) ,所有 \(xyz=i\) 的所有整数解\((x,y,z)\) , 求\((|x|+|y|+|z|)^2\) 的和。
由于对称性,所以我们只需要算第一卦限(\(x,y,z>0\))的答案,再乘4就行啦。
30分做法:暴力枚举\(i\),再暴力枚举满足\(xyz=i\) 的 \(x,y,z\),然后暴力计算答案。
60分做法:
首先,我们可以用\([1,b]\) 的答案减去 \([1,a-1]\) 的答案。
然后注意到\((x+y+z)^2=(x^2+y^2+z^2)+2(xy+yz+zx)\) , 其中两个括号里的三项都是对称式。于是我们可以单独算出所有的\(x^2\) 和 \(yz\) 对答案的贡献,再把前者加上后者乘2。
接下来推式子...公式恐惧症请做好心理准备。
设\(\sigma(n)\) 等于n的约数个数;
\\ans1=&\sum_{i=1}^N\sum_{xyz=i}x^2
\\=&\sum_{i=1}^N\sum_{x|i}x^2\sum_{yz=\frac i x}
\\=&\sum_{i=1}^N\sum_{x|i}x^2\sigma(\frac i x)
\\=&\sum_{x=1}^N x^2\sum_{x|i}\sigma(\frac i x)
\\=&\sum_{x=1}^N x^2\sum_{d\le \lfloor N/x\rfloor}\sigma(d)
\end{aligned}
\]
\\ans2=&\sum_{i=1}^N\sum_{xyz=i}yz
\\=&\sum_{i=1}^N\sum_{x|i}\sum_{yz=\frac i x}yz
\\=&\sum_{i=1}^N\sum_{x|i}\frac i x\sigma(\frac i x)
\\=&\sum_{i=1}^N\sum_{x|i}x\sigma(x)
\\=&\sum_{x=1}^N x\sigma(x)\lfloor \frac N x \rfloor
\end{aligned}
\]
\(ans=4*(ans1+2*ans2)\)
对于ans1,因为\(\lfloor \frac N x \rfloor\) 只有\(\sqrt N\) 种取值, 我们可以用一种经典的方法分段计算,再对后面的前缀和预处理出来,或者暴力求和,这样可以做到O(N)。
对于ans2,同样分段计算,再预处理\(x\sigma(x)\) 的前缀和,也是O(N)。
总复杂度:O(N)。如果你喜欢用一种NlgN的方法筛约数个数...那就是O(NlgN)。
现场有一位大爷用了筛法也过了60分,orz。
100分做法:
在60分做法的基础上,用杜教筛求\(\sigma(x)\) 和 \(x\sigma(x)\) 的前缀和,复杂度O(N^(2/3))。
详见唐老师博客:http://blog.csdn.net/skywalkert/article/details/50500009
T3
被喷是裸的数据结构题了啊...
观察题目中的要求,将变量看做点,方程看做边,只会形成一棵树。
30分做法:因为只有询问操作,我们先读入所有数据,建一棵树,每条边用两条有向边表示,权值分别为c和-c,然后dfs一遍,预处理出lca(或者你要树剖也行),然后处理询问。
100分做法:发现只要用LCT维护就行了。几个细节:边权不好维护,那么我们就插入虚拟的点来表示边。在询问一条链的时候,要求链上的方程是x1-x2=a, x2-x3=b, x3-x4=c...这样的形式,即要求符号的方向相同。我们可以让每条边上的方程表示子节点减父节点的值,然后换根的时候,发现只有新的根到原来的根的路径上的顺序要颠倒,于是在access的splaytree里面打一个tag取反。具体实现见代码。
代码
T1
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e5+5, MD=10007;
int in[MAXN], deg[MAXN], to[MAXN][10], K[MAXN], N;
int p[MAXN], M, f[MAXN], ans;
int read()
{
int r=0, c=getchar();
while(c<'0'||'9'<c) c=getchar();
while('0'<=c&&c<='9') r=r*10+c-'0', c=getchar();
return r;
}
int main()
{
scanf("%d", &N);
for(int i=1; i<=N; ++i){
K[i]=read();
for(int j=0; j<K[i]; ++j) in[to[i][j]=read()]++;
}
for(int i=1; i<=N; ++i)
if(!in[i]) f[p[M++]=i]=1;
for(int i=0; i<M; ++i){
int u=p[i];
for(int j=0; j<K[u]; ++j){
int v=to[u][j];
if(!(--in[v])) p[M++]=v;
}
}
for(int i=0; i<M; ++i){
int u=p[i];
for(int j=0; j<K[u]; ++j){
int v=to[u][j];
f[v]=(f[v]+f[u])%MD;
}
if(!K[u]) ans=(ans+f[u])%MD;
}
printf("%d\n", ans);
return 0;
}
T2
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 5e6+5, MD=10007;
int pr[MAXN], f[MAXN], g[MAXN], np, M;
short ip[MAXN];
void pre()
{
ip[1]=f[1]=1;
for(int i=2; i<M; ++i){
if(!ip[i]) pr[np++]=i, f[i]=2, g[i]=1;
for(int j=0, k, p; j<np; ++j){
p=pr[j], k=i*p;
if(k>=M) break;
ip[k]=1;
if(i%p==0){
f[k]=f[i]/(g[i]+1)*(g[i]+2);
g[k]=g[i]+1;
break;
}
f[k]=f[i]*2;
g[k]=1;
}
}
for(int i=1; i<M; ++i){
f[i]%=MD;
g[i]=(i*f[i]+g[i-1])%MD;
f[i]=(f[i]+f[i-1])%MD;
}
}
int F(int n)
{
if(n<M) return f[n];
int r=0;
for(int i=1, j; i<=n; i=j+1){
int t=n/i; j=n/t;
r=(r+(ll)(j-i+1)*t)%MD;
}
return r;
}
int G(int n)
{
if(n<M) return g[n];
int r=0;
for(int i=1, j; i<=n; i=j+1){
int t=n/i; j=n/t;
r=(r+((ll)(i+j)*(j-i+1)/2%MD)*t*(t+1)/2)%MD;
} return r;
}
int work(int n)
{
int l=0, c=0, r1=0, r2=0;
for(ll i=1, j; i<=n; i=j+1){
j=n/(n/i); c=(ll)j*(j+1)%MD*(2*j+1)*1668%MD;
r1=(r1+(ll)(c-l+MD)*F(n/i))%MD; l=c;
}
l=0;
for(ll i=1, j; i<=n; i=j+1){
j=n/(n/i); c=G(j);
r2=(r2+(ll)(c-l+MD)*(n/i))%MD; l=c;
}
return (r1+r2*2)*12%MD;
}
int main()
{
int a, b;
scanf("%d%d", &a, &b);
for(M=0; M*M*M<=b; M++);
M=min(MAXN, M*M);
pre();
printf("%d\n", (work(b)-work(a-1)+MD)%MD);
return 0;
}
T3
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 3e5+5, MD=6662333;
struct Node
{
Node *ch[2], *fa;
int rev, inv, w, sum;
}tr[MAXN], *nil=tr;
inline void init(int x)
{
tr[x].ch[0]=tr[x].ch[1]=tr[x].fa=nil;
}
inline void up(Node *x)
{
Node *l=x->ch[0], *r=x->ch[1];
x->sum=x->w+l->sum+r->sum;
}
inline void down(Node *x)
{
Node *l=x->ch[0], *r=x->ch[1];
if(x->inv){
l->inv^=1; l->sum=-l->sum; l->w=-l->w;
r->inv^=1; r->sum=-r->sum; r->w=-r->w;
x->inv=0;
}
if(x->rev){
l->rev^=1; r->rev^=1;
swap(x->ch[0], x->ch[1]);
x->rev=0;
}
}
inline int isrt(Node *x){return !(x->fa->ch[0]==x||x->fa->ch[1]==x);}
void rot(Node *x)
{
Node *y=x->fa, *z=y->fa; int l=y->ch[1]==x, r=!l;
if(!isrt(y)) z->ch[z->ch[1]==y]=x;
x->ch[r]->fa=y; y->fa=x; x->fa=z;
y->ch[l]=x->ch[r]; x->ch[r]=y;
up(y); up(x);
}
Node *st[MAXN]; int top;
void splay(Node *x)
{
st[top=0]=x;
for(Node *u=x; !isrt(u); u=u->fa) st[++top]=u->fa;
while(top>=0) down(st[top--]);
while(!isrt(x)){
Node *y=x->fa, *z=y->fa;
if(!isrt(y)) rot((z->ch[1]==y)^(y->ch[1]==x)?x:y);
rot(x);
}
}
void access(Node *x)
{
for(Node *t=nil; x!=nil; t=x, x=x->fa)
splay(x), x->ch[1]=t, up(x);
}
void mkrt(Node *x)
{
access(x); splay(x);
x->rev^=1; x->inv^=1; x->sum=-x->sum; x->w=-x->w;
}
void lnk(Node *x, Node *y)
{
mkrt(x); x->fa=y;
}
void cut(Node *x, Node *y)
{
mkrt(x); access(y); splay(y);
x->fa=y->ch[0]=nil;
}
Node *getrt(Node *x)
{
while(x->fa!=nil) x=x->fa;
return x;
}
int N, M, K, Q, ne;
inline int xht(int x){return x>0?x%K:(K-(-x)%K)%K;}
int ha[MAXN], hb[MAXN], he[MAXN], nxt[MAXN], hd[MD], nh=1;
void add(int a, int b, int e)
{
int k=((ll)a*b+a+b)%MD;
ha[nh]=a; hb[nh]=b; he[nh]=e; nxt[nh]=hd[k]; hd[k]=nh++;
}
int del(int a, int b)
{
int k=((ll)a*b+a+b)%MD;
for(int i=hd[k], j=0; i; i=nxt[i], j=i){
if((ha[i]==a&&hb[i]==b)||(ha[i]==a&&hb[i]==b)){
if(!j) hd[k]=nxt[i];
else nxt[j]=nxt[i];
return he[i];
}
}
return 0;
}
int main()
{
scanf("%d%d%d%d", &N, &M, &K, &Q);
ne=N+1;
for(int i=0; i<=N+M+Q; ++i) init(i);
for(int i=0; i<M; ++i){
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
// G[a][b]=G[b][a]=ne;
add(a, b, ne);
tr[ne].w=tr[ne].sum=c;
lnk(tr+a, tr+ne); lnk(tr+ne, tr+b);
ne++;
}
for(int i=0; i<Q; ++i){
int t, a, b, c;
scanf("%d%d%d", &t, &a, &b);
if(t==1){
scanf("%d", &c);
// G[a][b]=G[b][a]=ne;
add(a, b, ne);
tr[ne].w=tr[ne].sum=c;
lnk(tr+a, tr+ne); lnk(tr+ne, tr+b);
ne++;
}else if(t==2){
// int e=G[a][b];
int e=del(a, b);
if(e){
cut(tr+a, tr+e); cut(tr+e, tr+b);
// G[a][b]=G[b][a]=0;
}
}else{
scanf("%d", &c);
if(getrt(tr+a)==getrt(tr+b)){
mkrt(tr+a); access(tr+b); splay(tr+b);
printf("%d\n", xht(c-tr[b].sum));
}else puts("-1");
}
}
return 0;
}
【洛谷】xht模拟赛 题解的更多相关文章
- 洛谷mNOIP模拟赛Day1-斐波那契
题目背景 大样例下发链接:http://pan.baidu.com/s/1c0LbQ2 密码:jigg 题目描述 小 C 养了一些很可爱的兔子. 有一天,小 C 突然发现兔子们都是严格按照伟大的数学家 ...
- 【洛谷mNOIP模拟赛Day1】T1 斐波那契
题目传送门:https://www.luogu.org/problemnew/show/P3938 这题出得特别吼啊~~ 通过打表或者大胆猜想斐波那契数列的一些性质,我们不难发现对于一只兔子$x$,其 ...
- 洛谷noip 模拟赛 day1 T3
T7983 大芳的逆行板载 题目背景 大芳有一个不太好的习惯:在车里养青蛙.青蛙在一个n厘米(11n毫米s)的Van♂杆子上跳来跳去.她时常盯着青蛙看,以至于突然逆行不得不开始躲交叉弹.有一天他突发奇 ...
- 洛谷mNOIP模拟赛Day2-星空
题目背景 pdf题面和大样例链接:http://pan.baidu.com/s/1cawM7c 密码:xgxv 命运偷走如果只留下结果, 时间偷走初衷只留下了苦衷. 你来过,然后你走后,只留下星空. ...
- 洛谷mNOIP模拟赛Day1-分组
传送门 首先是贪心的思路 从后向前选,能多选就多选, 理由:数字越少肯定越优,同时间隔尽量向前推,字典序尽量小 对于K==1,枚举1~512直接判断 对于K==2,需要用镜像并查集,来刻画" ...
- 洛谷mNOIP模拟赛Day2-将军令
题目背景 pdf题面和大样例链接:http://pan.baidu.com/s/1cawM7c 密码:xgxv 历史/落在/赢家/之手 至少/我们/拥有/传说 谁说/败者/无法/不朽 拳头/只能/让人 ...
- 洛谷mNOIP模拟赛Day2-入阵曲
题目背景 pdf题面和大样例链接:http://pan.baidu.com/s/1cawM7c 密码:xgxv 丹青千秋酿,一醉解愁肠. 无悔少年枉,只愿壮志狂. 题目描述 小 F 很喜欢数学,但是到 ...
- 洛谷mNOIP模拟赛Day1-数颜色
传送门 题目大意: 给定一个序列,维护每个数字在[L,R]出现的次数以及交换a[x]和a[x+1]的操作 一开始想的分桶法,感觉复杂度还可以吧,常数有点大,于是死得很惨(65分) #include&l ...
- 洛谷noip 模拟赛 day1 T1
T7925 剪纸 题目描述 小芳有一张nnn*mmm的长方形纸片.每次小芳将会从这个纸片里面剪去一个最大的正方形纸片,直到全部剪完(剩下一个正方形)为止. 小芳总共能得到多少片正方形纸片? 输入输出格 ...
随机推荐
- Window.open()方法参数详解总结(转)
1, 最基本的弹出窗口代码 window.open('page.html'); 2, 经过设置后的弹出窗口 window.open('page.html', 'newwindow', 'hei ...
- HTTP 知新
REST 先从 REST 的角度来看看 HTTP 协议规范, URL:需要操作的对象,也就是资源 HTTP method:我要对该对象做什么(POST 增.DELETE 删.GET 查.PUT 和 P ...
- C++常用STL
目录 C++ 常用STL整理 容器和配接器 list(链表) stack(栈) queue(队列) priority_queue(优先队列) set(集合) vector(向量) map&&a ...
- C/C++-左值、右值及引用
目录 1.左值and右值 2.引用 3.左值引用的用途 4.std::move和std::swap C和C++中定义了引用类型(reference type),存在左值引用(lvalue refere ...
- Mac上基于hexo+GitHub搭建个人博客(一)
原文地址: http://fanjiajia.cn/2018/11/23/Mac%E4%B8%8A%E5%9F%BA%E4%BA%8Ehexo+GitHub%E6%90%AD%E5%BB%BA%E4% ...
- win7 redis
<?php /* windows下php安装redis扩展 php_redis下载地址:https://pecl.php.net/package/redis 点击redis安装版本后面的 DLL ...
- 安装与配置JDK
第一步:下载jdk-7-linux-i586.tar.gzwget -c http://download.oracle.com/otn-pub/java/jdk/7/jdk-7-linux-i586. ...
- JDBC连接数据库的过程
以连接MySQL为例: (1)加载MySQL数据库连接的驱动程序.到MySQL官网下载该驱动程序jar包,然后把包复制到WEB-INF/lib目录下,则JDBC会调用Class.forName()方法 ...
- 【NOIP模拟赛】就 反悔贪心
biubiu~~~ 这道题,考场上上来就dp然后发现怎么优化也不行.............最后发现是贪心............. 正解:带反悔的贪心,原理是,假设我们现在得到了取i个的最优解那么我 ...
- JQuery中的each()的使用
each()函数是基本上所有的框架都提供了的一个工具类函数,通过它,你可以遍历对象.数组的属性值并进行处理. jQuery和jQuery对象都实现了该方法,对于jQuery对象,只是把each方法简单 ...