CSP-S全国模拟赛第三场 【nan死了】
mmt
居然第一步膜化乘除 都没看出来,没救了...
大概是贡献前缀和优化的做法
巨兔式讲解:大家都学会了么?
咱发现有大量的 (i/j , i%j ) 同时 对很多 c 产生了贡献,咱可以去优化这一部分的转移,具体做法就是根据前面能加的后面也能加,然后一路累加且算贡献
对于小于根号的所有 i/j ,咱可以优化这一部分转移,然后对于大于根号的 i/j ,暴力算就好了,两者复杂度都是是 n 根号 n 的
//by Judge
#include<bits/stdc++.h>
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(Rg int i=(a),I=(b)-1;i>I;--i)
#define ll long long
#define eps 1e-8
using namespace std;
const int mod=123456789;
const int M=1e5+3;
typedef int arr[M];
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline int read(){ int x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} char sr[1<<21],z[20];int CCF=-1,Z;
inline void Ot(){fwrite(sr,1,CCF+1,stdout),CCF=-1;}
inline void print(int x,char chr='\n'){
if(CCF>1<<20)Ot();if(x<0)sr[++CCF]=45,x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++CCF]=z[Z],--Z);sr[++CCF]=chr;
} int n,bl; arr a,b,c; double inv[M];
#define Div(x,y) (int(x*inv[y]+eps))
int main(){ n=read(),bl=sqrt(n);
fp(i,1,n) inv[i]=1.0/i,a[i]=read(); fp(i,0,n-1) b[i]=read();
fp(x,1,bl) fp(y,0,x-1){ Rg ll now=-1; Rg int A,l,r; // i/j = x 步长 , y 初始位置
for(Rg int k=x+y;k<=n;k+=x) if(Div(k,Div(k,x))==x){ // 必须是可达状态 ,此时 j = k/x
if(now<0) l=r=Div(k,x),A=k%r,now=1ll*a[x]*b[A]%mod;
else{ ++r; if(Div(k,l)!=i) ++l; else A=k%l,now=(now+1ll*a[x]*b[A])%mod; }
c[k]=(c[k]+now)%mod; // 当前的 now 存在的之前的状态当前 k 也可达
}
}
fp(i,1,n) fp(j,1,i) if(Div(i,j)<=bl) break;
else c[i]=(c[i]+1ll*a[Div(i,j)]*b[i%j]%mod)%mod;
fp(i,1,n) print(c[i]); return Ot(),0;
}
Sabotage
艹...这 T2 ,真 tm 长芝士了 ,支配树的新奇打法...
一眼看不出是支配树,只觉得题面眼熟,然后发现其实算法更加熟...
然后发现支配树代码很长,调挂了,于是康康题解区对比找找自己哪里挂了,于是有了这次惊人的发现
可以说是支配树板子题辣,这里的常规做法就不说了,又臭又长 (艹)
这里用的方法很诡(qiao)异(miao),大概就是说咱把这个 DAG 缩一下,对于入度大于 2 的节点把 Fa 设为 所有父亲节点的 LCA ,求解的时候输出两个点 LCA 的深度就好了,至于两个点不在同一棵树上(或者是别的无解情况),是可以被非常自然的处理掉的(雾),于是正确性就有了感性理解下的保证
然后咱可以发现这里的 LCA 是要随着拓扑的进行可以同时维护的...所以就打不了小常数的树剖了,于是顺便重温了一下倍增 LCA (雾)
具体康康代码咯?
卡了下常,进了 Rank1 (可能您康到咱的代码之后就不是了)
//by Judge
#include<cstdio>
#include<iostream>
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(Rg int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(Rg int i=head[u],v=e[i].to;i;v=e[i=e[i].nxt].to)
using namespace std;
const int M=1e5+7;
typedef int arr[M];
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline int read(){ int x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} char sr[1<<21],z[20];int C=-1,Z;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
inline void print(int x,char chr='\n'){
if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]=chr;
} int n,m,pat,hd,tl,f[M][19]; arr head,lg,q,h,d;
struct Edge{ int to,nxt; }e[M<<1];
inline void add(int x,int y){ ++d[y];
e[++pat]=(Edge){y,head[x]},head[x]=pat;
}
inline int LCA(int u,int v){ if(h[u]>h[v]) swap(u,v);
for(Rg int i=0;h[v]-h[u];++i) if(((h[v]-h[u])>>i)&1) v=f[v][i]; if(u==v) return u;
fd(i,17,0) if(f[u][i]^f[v][i]) u=f[u][i],v=f[v][i]; return *f[u];
}
int main(){ n=read(),m=read(),lg[0]=-1;
Rg int x,y; fp(i,1,m) x=read(),y=read(),add(y,x);
fp(i,1,n) lg[i]=lg[i>>1]+1,*f[i]=!d[i]?q[++tl]=i,0:-1;
while(hd<tl){ x=q[++hd],h[x]=h[*f[x]]+1;
fp(i,1,lg[h[x]]) f[x][i]=f[f[x][i-1]][i-1];
go(x) *f[v]=*f[v]<0?x:LCA(x,*f[v]),!--d[v]&&(q[++tl]=v);
} m=read(); while(m--) x=read(),y=read(),print(h[LCA(x,y)]);
return Ot(),0;
}
LP
并没有什么特别的? 但是咱太菜了还是想不出来的那种
(看了题解后)不难想出 \(n*p^2\) 的 SB dp 方程 ,f[i][j][k]
看着数据范围应该是 np 的题目(NP-hard 可海星),那么怎么少掉一个 p ?
咱发现两个限制本质上是可以简化的,可以把 f 简化为 2 维的 f[i][j] ,j 表示对于选出的 b 之和小于等于 j 且 c 之和大于等于 j
然后两个转移方式(x 为 0 或 1)的 dp 转移,然后一个单调队列优化 x=1 时的转移就好了
空间继续优化,那么滚动可以解决,并且开数组变小了,代码常数却并没有怎么提高,所以隐隐起到了卡常的效果(空间小一般时间也会小,原因显而易见)
//by Judge
#include<cstdio>
#include<cstring>
#include<iostream>
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(Rg int i=(a),I=(b)-1;i>I;--i)
#define QwQ printf("IMPOSSIBLE!!!\n")
#define QvQ printf("%d\n",f[n&1][p])
using namespace std;
const int inf=2e9+7;
const int M=1e4+3;
typedef int arr[M];
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline bool cmin(int& a,int b){return a>b?a=b,1:0;}
inline int read(){ int x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} int n,p,head,tail,x,y; arr a,b,c,f[2],q,w;
inline void Solv(){ n=read(),p=read(); fp(i,1,n) a[i]=read();
fp(i,1,n) b[i]=read(); fp(i,1,n) c[i]=read(); fp(i,1,p) f[0][i]=inf;
fp(i,1,n){ head=1,tail=0,x=i&1,y=x^1; fp(j,0,p) f[x][j]=f[y][j];
fp(j,a[i],p){ while(head<=tail&&w[tail]>=f[y][j-a[i]]) --tail;
while(head<=tail&&q[head]<j-b[i]) ++head;
q[++tail]=j-a[i],w[tail]=f[y][q[tail]],cmin(f[x][j],w[head]+c[i]);
}
} f[n&1][p]<inf?QvQ:QwQ;
}
int main(){ int T=read();
while(T--) Solv(); return 0;
}
明天继续吧...
CSP-S全国模拟赛第三场 【nan死了】的更多相关文章
- 【noi.ac-CSP-S全国模拟赛第三场】#705. mmt
给定数组a[],b[] 求$$c_i=\sum_{j=1}^{i} a_{\left \lfloor \frac{n}{j} \right \rfloor}·b_{i \bmod j}$$ 大概就是对 ...
- NOI.AC NOIP模拟赛 第三场 补记
NOI.AC NOIP模拟赛 第三场 补记 列队 题目大意: 给定一个\(n\times m(n,m\le1000)\)的矩阵,每个格子上有一个数\(w_{i,j}\).保证\(w_{i,j}\)互不 ...
- [NOI.AC 2018NOIP模拟赛 第三场 ] 染色 解题报告 (DP)
题目链接:http://noi.ac/contest/12/problem/37 题目: 小W收到了一张纸带,纸带上有 n个位置.现在他想把这个纸带染色,他一共有 m 种颜色,每个位置都可以染任意颜色 ...
- CSP-S全国模拟赛第四场 【nan?】
本来想抢三题的 rk1 ?[无耻 最后发现 T2 好像还是慢了些,只搞了个 rk2 子段与子段 第一题随便分析一下,发现一段区间中某个元素的贡献次数就是 \((x+1)·(y+1)\) x 是他左边的 ...
- NOI2019省选模拟赛 第三场
传送门 明明没参加过却因为点进去结果狂掉\(rating\)-- \(A\) 集合 如果我们记 \[f_k=\sum_{i=1}^nT^i{n-i\choose k}\] 那么答案显然就是\(f_{k ...
- 「NOWCODER」CSP-S模拟赛第3场
「NOWCODER」CSP模拟赛第3场 T1 货物收集 题目 考场思路即正解 T2 货物分组 题目 考场思路 题解 60pts 算法:一维 DP 100pts 算法:一维 DP ?线段树 + 单调栈 ...
- NOI.AC NOIP模拟赛 第五场 游记
NOI.AC NOIP模拟赛 第五场 游记 count 题目大意: 长度为\(n+1(n\le10^5)\)的序列\(A\),其中的每个数都是不大于\(n\)的正整数,且\(n\)以内每个正整数至少出 ...
- NOI.AC NOIP模拟赛 第六场 游记
NOI.AC NOIP模拟赛 第六场 游记 queen 题目大意: 在一个\(n\times n(n\le10^5)\)的棋盘上,放有\(m(m\le10^5)\)个皇后,其中每一个皇后都可以向上.下 ...
- NOI.AC NOIP模拟赛 第四场 补记
NOI.AC NOIP模拟赛 第四场 补记 子图 题目大意: 一张\(n(n\le5\times10^5)\)个点,\(m(m\le5\times10^5)\)条边的无向图.删去第\(i\)条边需要\ ...
随机推荐
- Github 已经托管超过 1000 万个项目库
2013 年对 Github 来说是不可思议和富有成效的一年,几天前 Github.com 上托管的项目已经超过 1000 万. 在此之前,首个 100 万项目用了将近 4 年时间,具体是 3 年 8 ...
- Nginx配置记录【例3】
C服务器,例: [root@82_www_db_2 conf.d]# egrep -v "^#|^$" /etc/nginx/nginx.conf user nginx; work ...
- Struts初学
自我概述 今天看了Struts,感觉这是个非常好用的东西!虽然它已经过时了,被springMVC取代了,但是仍然有了解的价值. 可是在学习过程中遇到了很多问题,比如其中一些原理很是抽象,有一些问题莫名 ...
- Python--安装第三方库的方法
一:安装方法(以numpy为例,安装其他包把numpy改为包名即可) 1.有设置python包中pip.exe环境变量的情况下 同时按住win+R输入cmd打开cmd,直接输入pip install ...
- Dark 类与对象
1 类的声明 使用class声明一个类 使用new 创建一个对象,new可省略 dark文件名和声明的类名可以不一样,与java不同 void main() { var function = Pers ...
- mybatis的xml文件中的CDATA的使用
mybatis的xml文件中的CDATA的使用 <!--查询列表--> <select id="queryListPage" parameterType=&quo ...
- windows触摸板速度调整
Windows 触摸板滚动速度调整: 在注册表中: The magic key is: Computer\HKEY_CURRENT_USER\Software\Microsoft\Wisp\Tou ...
- 【工具】rinetd 使用教程(linux 下的端口转发工具 )
日期:2019-07-30 20:00:36 更新: 作者:Bay0net 介绍:使用 rinetd 来转发某端口的流量. 0x01. 安装 官网 RINETD 安装方法很简单,一条语句就 OK 了. ...
- Python字符和字符值(ASCII或Unicode码值)转换方法
Python字符和字符值(ASCII或Unicode码值)转换方法 这篇文章主要介绍了Python字符和字符值(ASCII或Unicode码值)转换方法,即把字符串在ASCII值或者Unicode值之 ...
- 微信小程序---绘图
传送门: https://mp.weixin.qq.com/debug/wxadoc/dev/api/canvas/reference.html