X000101
P3879 [TJOI2010]阅读理解
考虑用 Trie 解决
#include<stdio.h>
#include<bitset>
#include<string.h>
#define rep(i,n) for (int i=0; i<n; ++i)
int n,m,t=1,cnt=1,l,*p,a[500000][26];
char c[20]; std::bitset<1010>v[500000];
int main() {
scanf("%d",&n);
rep(i,n) for (scanf("%d",&m); m; --m) {
scanf("%s",c),l=strlen(c),p=&t;
rep(j,l) p=&a[*p][c[j]-97],*p||(*p=(++cnt));
v[*p][i]=1;
}
for (scanf("%d",&m); m; --m,putchar('\n')) {
scanf("%s",c),l=strlen(c),p=&t;
for (int i=0; i<l&&*p; ++i) p=&a[*p][c[i]-97];
rep(i,n) v[*p][i]&&(printf("%d ",i+1),0);
}
return 0;
}
其实是很裸的模板题了 主要问题在于空间占用
首先可以用 bitset
代替 bool
数组来省空间
然后要考虑 Trie 包含的节点个数
容易看出节点个数不超过所有文章的总字母数,也就是 \(5\times 10^6\)
但是按这个上界开数组肯定空间爆炸
因为单词前缀重合较多、数据良心等原因,实际上节点个数远远达不到这个级别
所以开到 \(5\times 10^5\) 就够了 同时也不会MLE
P6392 中意
求 \(ans=\left\lceil \dfrac{b\times 2^{a+2}}{25} \right\rceil \times 100\) 的值
当 \(25 | b\times 2^{a+2}\) ,即 \(25 | b\) 时,上取整可以直接去掉,\(ans=4b\times 2^{a+2}\)
若 \(25 \nmid b\) ,则上取整相当于下取整再加 1 , \(ans=\left\lfloor \dfrac{b\times 2^{a+2}}{25}\right\rfloor\times100+100\)
而 \(\left\lfloor \dfrac{b\times 2^{a+2}}{25}\right\rfloor=\dfrac{b\times 2^{a+2}-(b\times 2^{a+2}\bmod 25)}{25}\)
代入得 \(ans=4[b\times 2^{a+2}-(b\times 2^{a+2}\bmod 25)]+100\)
务必注意对 \(25\) 取模之前不要对 \(998344353\) 取模
\(b\) 非常大,所以读入时就要取模,模 \(25\) 和模 \(998344353\) 也要分开算
#include<stdio.h>
#include<ctype.h>
const int P=998344353,p=25;
int s1,s2,x1=2,x2=2; long long a; char ch;
int main() {
for (ch=getchar(); isdigit(ch); ch=getchar())
s1=(10ll*s1+(ch^48))%P,s2=(s2*10+(ch^48))%p;
for (scanf("%lld",&a),a+=2; a; a>>=1)
(a&1)&&(s1=1ll*s1*x1%P,s2=s2*x2%p),
x1=1ll*x1*x1%P,x2=x2*x2%p;
s1=4ll*(s1-s2+P)%P,s2&&(s1=(s1+100)%P);
printf("%d\n",s1);
return 0;
}
P5677 [GZOI2017]配对统计
首先研究一下“好的配对”
其实就是先确定 \(a_x\) ,要找到 \(a_y\) 使两者差的绝对值最小
对 \(a\) 排序,那么符合条件的 \(a_y\) 排序后肯定与 \(a_x\) 相邻
很容易就能找出所有“好的配对” \((x,y)\)
注意 \((x,y)\) 和 \((y,x)\) 其实是有区别的,但是在查询的时候两者等价,所以不妨令 \(x<y\)
然后来处理查询
同时考虑左右边界不方便,所以我们通过排序先处理掉一边
将所有查询离线,按右边界 \(r\) 的大小升序排序
再将所有“好的配对”按靠右元素的位置 \(y\) 升序排序
处理询问 \(i\) 时,要考虑所有满足 \(y\le r_i\) 的配对
所以我们在完成了询问 \(1\sim i-1\) 的基础上,只需要再加入 \(r_{i-1}<y\le r_i\) 的配对即可
左边界要求 \(x\ge l_i\)
用树状数组存储已加入的配对中靠左元素的位置 \(x\)
那么这就是个裸的区间查询了
最后要按照题目要求计算答案
时间复杂度为 \(O(n\log n)\) (认为 \(n,m\) 同级)
#include<stdio.h>
#include<ctype.h>
#include<algorithm>
#define gc (l==r&&(r=(l=c)+fread(c,1,1<<21,stdin),l==r)?EOF:*l++)
const int N=300010,inf=2e9; long long ans;
int n,m,cnt,t,f[N];
inline int lb(int x) { return (-x&x); }
inline void upd(int i) {
for ( ; i<=n; i+=lb(i)) ++f[i];
}
inline int qry(int i) {
int s=0;
for ( ; i; i-=lb(i)) s+=f[i];
return s;
}
char c[1<<21],*l=c,*r=c;
inline int read() {
int x=0; char ch=gc;
while (!isdigit(ch)) ch=gc;
while (isdigit(ch)) x=x*10+(ch^48),ch=gc;
return x;
}
struct node { int i,x; }a[N];
struct match { int l,r; }b[N];
struct query { int i,l,r; }q[N];
int operator < (node p,node q) { return p.x<q.x; }
int operator < (match p,match q) { return p.r<q.r; }
int operator < (query p,query q) { return p.r<q.r; }
inline void add(int x,int y) {
x>y&&(t=x,x=y,y=t);
b[++cnt]={x,y};
}
int main() {
n=read(),m=read();
for (int i=1; i<=n; ++i) a[i]={i,read()};
std::sort(a+1,a+n+1),a[0].x=-inf,a[n+1].x=inf;
for (int i=1; i<=n; ++i) //找出所有“好的配对”
a[i].x-a[i-1].x<=a[i+1].x-a[i].x&&(add(a[i].i,a[i-1].i),0),
a[i].x-a[i-1].x>=a[i+1].x-a[i].x&&(add(a[i].i,a[i+1].i),0);
for (int i=1; i<=m; ++i) t=read(),q[i]={i,t,read()};
std::sort(b+1,b+cnt+1),std::sort(q+1,q+m+1);
for (int i=1,j=1; i<=m; ++i) {
while (b[j].r<=q[i].r&&j<=cnt) upd(b[j].l),++j; //加入配对
ans+=1ll*q[i].i*(j-1-qry(q[i].l-1)); //j-1为已加入的配对数
}
printf("%lld\n",ans); //要开long long
return 0;
}
P2233 [HNOI2002]公交车路线
显然可以递推
用 \(f_{i,j}\) 表示换了 \(i\) 次车最终到达 \(j\) 站的方案数( \(j=0\sim7\) 依次对应 \(A\sim H\) )
则有 \(\begin{cases}
f_{i,0}=f_{i-1,1}+f_{i-1,7}\\
f_{i,1}=f_{i-1,0}+f_{i-1,2}\\
f_{i,2}=f_{i-1,1}+f_{i-1,3}\\
f_{i,3}=f_{i-1,2}\\
f_{i,4}=f_{i-1,3}+f_{i-1,5}\\
f_{i,5}=f_{i-1,6}\\
f_{i,6}=f_{i-1,5}+f_{i-1,7}\\
f_{i,7}=f_{i-1,0}+f_{i-1,6}
\end{cases}\)
注意到达 \(E\) 站之后就不会再换车了,所以 \(f_{i,3},f_{i,5}\) 与 \(f_{i-1,4}\) 无关
直接递推时间复杂度是 \(O(n)\) 的,可以通过
但这是 2002 年的省选题,在当时的评测机配置下显然会超时
实际上我们可以把递推式写成矩阵乘法的形式
\(\begin{bmatrix}f_{i,0}\\f_{i,1}\\f_{i,2}\\f_{i,3}\\f_{i,4}\\f_{i,5}\\f_{i,6}\\f_{i,7}\end{bmatrix}=
\begin{bmatrix}
0&1&0&0&0&0&0&1\\
1&0&1&0&0&0&0&0\\
0&1&0&1&0&0&0&0\\
0&0&1&0&0&0&0&0\\
0&0&0&1&0&1&0&0\\
0&0&0&0&0&0&1&0\\
0&0&0&0&0&1&0&1\\
1&0&0&0&0&0&1&0\end{bmatrix}
\begin{bmatrix}f_{i-1,0}\\f_{i-1,1}\\f_{i-1,2}\\f_{i-1,3}\\f_{i-1,4}\\f_{i-1,5}\\f_{i-1,6}\\f_{i-1,7}\end{bmatrix}\)
然后写个矩阵加速就可以 \(O(8^3\log n)\) 解决了
#include<stdio.h>
#include<string.h>
#define rep(i) for (int i=0; i<8; ++i)
struct matrix { int c[8][8]; }a,f,t;
matrix operator * (matrix x,matrix y) {
memset(t.c,0,sizeof t.c);
rep(i) rep(j) {
rep(k) t.c[i][j]+=x.c[i][k]*y.c[k][j];
t.c[i][j]%=1000;
}
return t;
}
int main() {
f=a={ { {0,1,0,0,0,0,0,1},
{1,0,1,0,0,0,0,0},
{0,1,0,1,0,0,0,0},
{0,0,1,0,0,0,0,0},
{0,0,0,1,0,1,0,0},
{0,0,0,0,0,0,1,0},
{0,0,0,0,0,1,0,1},
{1,0,0,0,0,0,1,0} } };
int n; scanf("%d",&n),--n;
while (n) (n&1)&&(f=f*a,0),a=a*a,n>>=1;
printf("%d\n",f.c[4][0]);
return 0;
}
P4317 花神的数论题
终于看懂了兔队做法 实在太强了%%%
\(\operatorname{sum}(i)\) 的取值范围很小,可以考虑统计每个取值的出现次数
用 \(f_{i,j}\) 表示最高 \(i\) 位中有 \(j\) 个 \(1\) ,且小于 \(n\) 的数的个数
(总位数与 \(n\) 的二进制表示位数保持一致,不够补前导零)
(因为 \(n\le 10^{15}<2^{50}\) ,所以实现的时候统一补到 \(50\) 位)
(不比较第 \(i\) 位之后的数,也就是严格地说,应为最高 \(i\) 位构成的数小于 \(n\) 最高 \(i\) 位构成的数)
若前 \(i-1\) 位构成的数已经小于 \(n\) 前 \(i\) 位构成的数,则第 \(i\) 位为 \(1,0\) 均合法
对应的转移方程为 \(f_{i,j}=f_{i-1,j-1}+f_{i-1,j}\)
还需要注意一个特殊情况:若 \(n\) 的第 \(i\) 位为 \(1\) ,那么令前 \(i-1\) 位数字与 \(n\) 的完全相同,第 \(i\) 位数字取 \(0\) ,得到的数也是小于 \(n\) 的
此时 \(1\) 的个数即为 \(n\) 前 \(i-1\) 为中 \(1\) 的个数(设为 \(t\) )
因此,若 \(n\) 的第 \(i\) 位为 \(1\) ,则 \(f_{i,t}\) 应再加 \(1\)
然后 dp 部分就结束了,最后用快速幂计算答案
注意 dp 过程中最好不要取模, \(f_{i,j}\) 最后是在指数上的,而且 \(10000007\) 不是质数,取模必须使用扩展欧拉定理,会比较麻烦
#include<stdio.h>
const int P=10000007;
int t,ans=1; long long n,f[50];
inline int power(int x,long long y) {
int s=1;
while (y) (y&1)&&(s=1ll*s*x%P),x=1ll*x*x%P,y>>=1;
return s;
}
int main() {
scanf("%lld",&n);
for (int i=49; ~i; --i) {
for (int j=49; j; --j) f[j]+=f[j-1];
((n>>i)&1)&&(++f[t],++t);
}
++f[t];
for (int i=1; i<=49; ++i)
ans=1ll*ans*power(i,f[i])%P;
printf("%d\n",ans);
return 0;
}
AT5140 [AGC035C] Skolem XOR Tree
很好的构造题
考察到异或的性质:对于偶数 \(x\) , \(x\oplus x+1=1\)
按下图所示方法构造,即可使 \(2i\) 到 \(n+2i\) 、 \(2i+1\) 到 \(n+2i+1\) 的路径均满足题意
但 \(n+1\) 的构造无法这样给出
样例中 \(n=3\) 的情况提示我们 \(1\oplus 2\oplus 3=0\) ,因此直接将 \(1,2,3,n+1,n+2,n+3\) 顺次相连即可
(这改变了 \(2,3,n+2,n+3\) 之间连边的构造方法,但其它节点的依然不变)
最后,如果 \(n\) 为偶数,我们还要考虑 \(n\) 和 \(2n\) 如何构造
最简单的方法是构造路径 \(n-x-1-y-2n\)
\(x,y\) 应与 \(1\) 直接相连,即 \(1<x,y\le n\) 且 \(x\ne 3,y\ne 3\)
还要满足 \(n\oplus x\oplus 1\oplus y\oplus n=n\) ,即 \(x\oplus y=n\oplus 1\)
随便找一组合法的 \(x,y\) 即可
我选的是 \(x=\operatorname{lowbit}(n),y=n\oplus 1\oplus x\)
无解条件:\(n\) 为 \(2\) 的整数次幂,此时无法给出 \(n\) 和 \(2n\) 的构造
#include<stdio.h>
inline void edge(int x,int y) { printf("%d %d\n",x,y); }
int main() {
int n,t; scanf("%d",&n),t=(-n&n); // t=lowbit(n)
if (t==n) return puts("No"),0; //无解
puts("Yes"),edge(1,2),edge(2,3),
edge(3,n+1),edge(n+1,n+2),edge(n+2,n+3);
for (int i=4; i<n; i+=2)
edge(1,i),edge(i,n+i+1),
edge(1,i+1),edge(i+1,n+i);
if ((n&1)==0) edge(t,n),edge(n^t^1,n+n);
return 0;
}
X000101的更多相关文章
随机推荐
- Differential Evolution: A Survey of the State-of-the-Art
@ 目录 概 主要内容 DE/rand/1/bin DE/?/?/? DE/rand/1/exp DE/best/1 DE/best/2 DE/rand/2 超参数的选择 的选择 的选择 的选择 一些 ...
- Mybatis获取自增主键的值
pojo: public class User { private Integer id; private String name; private String pwd; setter和getter ...
- 智慧巨鹿使用Rainbond落地实践,一个平台管理所有应用系统
背景 大家好,我是北京数立通科技有限公司的李栋.最近几年,我一直负责"智慧巨鹿"这一智慧城市项目的运行与维护工作.这个项目涉及到10多家供应商开发的 30 多套智慧城市应用的运维管 ...
- Ubuntu18.04 + Windows10 双系统安装
此处忽略Windows10安装!!! 准备 安装环境 OS:Windows10 CPU:Intel(R) Core(TM) i5-10600KF CPU @ 4.10GHz 4.10 GHz GPU: ...
- django 字段默认值
default 表示在页面中默认选中状态的值 页面为 来自为知笔记(Wiz)
- JMeter_请求参数
在做接口测试时,发送请求的参数有两种格式,一种是Parameters,一种是JSON 一.Jmeter传参 JMeter 传Parameters格式的参数 JMeter 传JSON格式的参数 二.区分 ...
- nginx 超时时间配置说明
做excel文件导入时 报 504 错误 是nginx网关超时导致 下面几个参数貌似没效果,反正我配置不起作用 这是有问题的配置属性 ,注意 于是我换了配置 ,放在http块里 ,配置生效了 #读 ...
- Centos安装DenyHosts
一.背景 个人申请的腾讯云主机被扫描端口,数百次登录失败的尝试 解决方法:安装工具,记录并屏蔽恶意访问. 二.检查环境 系统安装的sshd是否支持tcp_wrappers(默认都支持) ldd /us ...
- 服务限流 -- 自定义注解基于RateLimiter实现接口限流
1. 令牌桶限流算法 令牌桶会以一个恒定的速率向固定容量大小桶中放入令牌,当有浏览来时取走一个或者多个令牌,当发生高并发情况下拿到令牌的执行业务逻辑,没有获取到令牌的就会丢弃获取服务降级处理,提示一个 ...
- iframe页面总是提示需要重新登录怎么办
原文链接:iframe页面二次登录问题 生产问题 问题背景 由于历史原因,公司内部系统有一些页面是基于iframe嵌入的其他系统的页面,之前一直运行正常,最近不知什么原因接连出现访问所有iframe页 ...