noi2017 day1 题解
d1t1
sol1:用线段树维护区间是否全0/全1,叶子上压位维护对应位置的数位,加法首先对叶子加,如需进位则向右找到第一个不是全1的叶子+1,中间部分全1部分打上反转标记,减法同理。
#include<cstdio>
int _(){
int x=,f=,c=getchar();
while(c<)c=='-'?f=-:,c=getchar();
while(c>)x=x*+c-,c=getchar();
return x*f;
}
const int N=;
typedef unsigned int u32;
int n,_l,flag;
u32 _ans;
int mx;
struct node{
node*lc,*rc;
int rev;
u32 _or,_and;
void revs(){
rev^=;
_or=~_or;
_and=~_and;
}
void up(){
_or=lc->_or|rc->_or;
_and=lc->_and&rc->_and;
}
void dn(){
if(rev){
rev^=;
lc->revs();
rc->revs();
}
}
void find(int L,int R){
if(L==R){
_ans=_or;
return;
}
int M=(L+R)>>;
dn();
if(_l<=M)lc->find(L,M);
else rc->find(M+,R);
}
void inc(int L,int R){
if(L==R){
flag=(_and+_ans<_and);
_and+=_ans;
_or=_and;
return;
}
int M=(L+R)>>;
dn();
if(_l<=M)lc->inc(L,M);
else rc->inc(M+,R);
up();
}
void dec(int L,int R){
if(L==R){
flag=(_and-_ans>_and);
_and-=_ans;
_or=_and;
return;
}
int M=(L+R)>>;
dn();
if(_l<=M)lc->dec(L,M);
else rc->dec(M+,R);
up();
}
void inc1(int L,int R){
if(flag)return;
if(_l<=L){
if(_and==~0u)return revs();
if(L==R){
_or=++_and;
flag=;
return;
}
}
dn();
int M=(L+R)>>;
if(_l<=M)lc->inc1(L,M);
rc->inc1(M+,R);
up();
}
void dec1(int L,int R){
if(flag)return;
if(_l<=L){
if(_or==0u)return revs();
if(L==R){
_or=--_and;
flag=;
return;
}
}
dn();
int M=(L+R)>>;
if(_l<=M)lc->dec1(L,M);
rc->dec1(M+,R);
up();
}
}ns[N*],*np=ns,*rt;
node*build(int L,int R){
node*w=np++;
if(L<R){
int M=(L+R)>>;
w->lc=build(L,M);
w->rc=build(M+,R);
}
w->_or=w->_and=w->rev=;
return w;
}
void inc(u32 a,int x){
if(!a)return;
_ans=a;_l=x;
rt->inc(,mx);
if(flag){
flag=;
_l=x+;
rt->inc1(,mx);
}
}
void dec(u32 a,int x){
if(!a)return;
_ans=a;_l=x;
rt->dec(,mx);
if(flag){
flag=;
_l=x+;
rt->dec1(,mx);
}
}
int main(){
n=_();_();_();_();
mx=n+;
if(mx<)mx=;
rt=build(,mx);
for(int i=;i<n;++i){
if(_()==){
int a0=_(),b=_();
int b1=b>>,b2=b&;
if(a0>){
u32 a=a0;
inc(a<<b2,b1);
if(b2)inc(a>>(-b2),b1+);
}else if(a0<){
u32 a=-a0;
dec(a<<b2,b1);
if(b2)dec(a>>(-b2),b1+);
}
}else{
int k=_();
_l=k>>;
rt->find(,mx);
printf("%d\n",_ans>>(k&)&);
}
}
return ;
}
sol2:用两个高精度数分别记录加法和减法的贡献,用线段树维护这两个数不同的数位,查询某一位时考虑两数当前位以及两数低位的大小关系可以得出答案。
#include<cstdio>
int _(){
int x;
scanf("%d",&x);
return x;
}
const int N=<<|,mx=<<;
int n;
bool v1[N],v2[N],tr[N*];
int l,r;
void add(bool*v,int x){
for(;v[x];v[x++]=);
v[x]=;
if(x>r)r=x;
}
int pre(int x){
for(x+=mx;x;x>>=)if(x&&tr[x^]){
for(x^=;x<mx;x=x<<^tr[x<<^]);
return x-mx;
}
return -;
}
int main(){
n=_();_();_();_();
for(int i=;i<n;++i){
if(_()==){
int a=_(),b=_();
if(!a)continue;
l=r=b;
if(a>){
for(int i=;i<=;++i)if(a>>i&)add(v1,b+i);
}else{
a=-a;
for(int i=;i<=;++i)if(a>>i&)add(v2,b+i);
}
for(int i=l;i<=r;++i)tr[i+mx]=v1[i]^v2[i];
for(l=(l+mx)>>,r=(r+mx)>>;l;l>>=,r>>=){
for(int i=l;i<=r;++i)tr[i]=tr[i<<]|tr[i<<^];
}
}else{
int x=_(),p=pre(x);
puts(tr[x+mx]^(p!=-&&v1[p]<v2[p])?"":"");
}
}
return ;
}
d1t2
预处理询问涉及的串的hash值,用散列表离散化,对每次修改操作,枚举新产生/消失的长度<=50的子串,若其hash值等于某个询问,则对应在散列表上记录贡献。
#include<cstdio>
#include<cstring>
#include<vector>
typedef unsigned long long u64;
const int P=,N=,Q=,pz=,H=<<;
int _(){
int x=,f=,c=getchar();
while(c<)c=='-'?f=-:,c=getchar();
while(c>)x=x*+c-,c=getchar();
return x*f;
}
int n,m,mk=;
int v[N],nx[N],pv[N];
char ss[];
u64 h1[],pp[];
int qs[Q][];
std::vector<int>qv[Q];
u64 hx[H+];
int hy[H+];
int ins(u64 x){
int w=(x^x>>^x>>)&(H-);
while(hx[w]){
if(hx[w]==x)return w;
w=(w+)&(H-);
}
hx[w]=x;
return w;
}
bool inc(u64 x,int a){
int w=(x^x>>^x>>)&(H-);
while(hx[w]){
if(hx[w]==x){
hy[w]+=a;
return ;
}
w=(w+)&(H-);
}
return ;
}
int ls[],lp,t0[];
int ms[],mp=;
int min(int a,int b){return a<b?a:b;}
int max(int a,int b){return a>b?a:b;}
void chk(int a,int b,int c){
lp=mp=;
for(int i=,w=a;i<mk&&w;++i,w=pv[w])ls[lp++]=v[w];
for(int i=lp-;i>=;--i)ms[++mp]=ls[i];
for(int i=,w=b;i<mk&&w;++i,w=nx[w])ms[++mp]=v[w];
for(int i=;i<=mp;++i)h1[i]=h1[i-]*pz+ms[i];
for(int i=;i<lp;++i){
int r=min(mp,i+mk);
for(int j=lp+;j<=r;++j){
inc(h1[j]-h1[i]*pp[j-i],c);
}
}
}
int main(){
n=_();m=_();
pp[]=;
for(int i=;i<=;++i)pp[i]=pp[i-]*pz;
for(int i=;i<=n;++i)++t0[v[i]=_()];
for(int i=;i<=m;++i){
qs[i][]=_();
if(qs[i][]==){
qs[i][]=_();
qs[i][]=_();
}else if(qs[i][]==){
qs[i][]=_();
}else{
scanf("%s",ss+);
int len=strlen(ss+);
int k=_();
if(k>mk)mk=k;
for(int j=;j<=len;++j)h1[j]=h1[j-]*pz+ss[j]-'';
qv[i].resize(max(len-k+,));
for(int j=k;j<=len;++j){
qv[i][j-k]=ins(h1[j]-h1[j-k]*pp[k]);
}
}
}
for(int i=;i<=;++i)inc(i,t0[i]);
for(int i=;i<=m;++i){
if(qs[i][]==){
int a=qs[i][],b=qs[i][];
nx[a]=b;pv[b]=a;
chk(a,b,);
}else if(qs[i][]==){
int a=qs[i][],b=nx[a];
nx[a]=pv[b]=;
chk(a,b,-);
}else if(qs[i][]==){
int ans=;
for(int j=;j<qv[i].size()&&ans;++j){
ans=u64(ans)*hy[qv[i][j]]%P;
}
printf("%d\n",ans);
}
}
return ;
}
d1t3
询问=k拆成<=k和<=k-1
只需考虑原矩形每一列最下面的一个可选位置,令f[x][y]表示最下方x行可选,第x+1行存在不可选位置,宽度y的矩形 合法的概率,则
$f[x][y]=\sum_{i=0}^{y-1}f[>=x][i]f[>x][y-1-i]$
这里dp不处理x=0的部分,只考虑x>0,因此0<xy<=k,暴力转移的时间复杂度可以接受
把0的影响表示为一个常系数线性齐次递推的形式,转化为多项式幂取模计算
#include<cstdio>
#include<cstring>
const int P=;
typedef long long i64;
const i64 X=(1ll<<)/P*P;
int pw(int a,int n){
int v=;
for(;n;n>>=,a=i64(a)*a%P)if(n&)v=i64(v)*a%P;
return v;
}
int n,m,q,A,B;
int f[][],g[][],cs[],v[],f0[],a0[],a1[];
i64 c[];
void mul(int*a,int*b,int m){
memset(c,,sizeof(c));
for(int i=;i<=m;++i){
for(int j=;j<=m;++j)c[i+j]+=i64(a[i])*b[j];
if(i%==||i==m)for(int j=;j<=m+i;++j)c[j]-=(c[j]>>)*X;
}
for(int i=m*;i>m;--i){
c[i]%=P;
for(int j=;j<=m+;++j)c[i-j]+=c[i]*v[j];
if((m*-i)%==)for(int j=;j<i;++j)c[j]-=(c[j]>>)*X;
}
for(int i=;i<=m;++i)a[i]=c[i]%P;
}
int cal(int n,int m,int q){
if(!m)return pw(-q,n);
memset(f,,sizeof(f));
memset(g,,sizeof(g));
g[m+][]=;
cs[]=-q;
for(int i=;i<=m;++i)cs[i]=cs[i-]*i64(q)%P;
for(int i=m;i;--i){
memcpy(g[i],g[i+],sizeof(g[]));
for(int j=;j<=m/i;++j){
for(int k=;k<j;++k){
f[i][j]=(f[i][j]+i64(g[i][k])*g[i+][j--k])%P;
}
f[i][j]=i64(cs[i])*f[i][j]%P;
g[i][j]=(f[i][j]+g[i][j])%P;
}
}
for(int i=;i<=m+;++i)v[i]=g[][i-]*i64(cs[])%P;
f0[]=pw(cs[],P-);
for(int i=;i<=m+;++i){
f0[i]=;
for(int j=;j<=i;++j)f0[i]=(f0[i]+f0[i-j]*i64(v[j]))%P;
}
memset(a0,,sizeof(a0));
memset(a1,,sizeof(a1));
a0[]=a1[]=;
for(;n;n>>=,mul(a1,a1,m))if(n&)mul(a0,a1,m);
int s=;
for(int i=;i<=m;++i)s=(s+i64(a0[i])*f0[i])%P;
return s;
}
int main(){
scanf("%d%d%d%d",&n,&m,&A,&B);
++n;
q=i64(A)*pw(B,P-)%P;
int s=(cal(n,m,q)-cal(n,m-,q))%P;
printf("%d\n",(s+P)%P);
return ;
}
noi2017 day1 题解的更多相关文章
- THUSC2017 Day1题解
THUSC2017 Day1题解 巧克力 题目描述 "人生就像一盒巧克力,你永远不知道吃到的下一块是什么味道." 明明收到了一大块巧克力,里面有若干小块,排成n行m列.每一小块都有 ...
- BZOJ4946 & 洛谷3826 & UOJ318:[NOI2017]蔬菜——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4946 https://www.luogu.org/problemnew/show/P3826 ht ...
- 【NOIP2014】Day1题解+代码
Day1 T1 签到题,模拟一下随便写就能过. 不过小心像我一样表打错傻逼的调了10min. #include <algorithm> #include <iostream> ...
- ZJOI2019 Day1 题解
想要继续向前,就从克服内心的恐惧开始. 麻将 题意 在麻将中,我们称点数连续的三张牌或三张点数一样的成为面子,称两张点数一样的牌为对子.一副十四张麻将牌的胡牌条件是可以分成四个面子和一个对子或者分成七 ...
- Noip 2016 Day1 题解
老师让我们刷历年真题, 然后漫不经心的说了一句:“你们就先做做noip2016 day1 吧” ...... 我还能说什么,,,,,老师你这是明摆着伤害我们啊2333333333 预计分数:100+2 ...
- NOI 2016 Day1 题解
今天写了NOI2016Day1的题,来写一发题解. T2 网格 题目传送门 Description \(T\) 次询问,每次给出一个 \(n\times m\) 的传送门,上面有 \(c\) 个位置是 ...
- 十连测Day1 题解
A. 奥义商店 有一个商店,n个物品,每个物品有一个价格和一种颜色. 有m个操作,操作有两种,一种是修改一个位置的价格,另一种是购买,每次购买指定一个公差d和一个位置k,找到包含这个位置k公差为d的同 ...
- 【NOIP2013】DAY1题解+代码
T1 傻逼快速幂,敲敲就过了. 我跟你们讲个笑话当时我以为这个数据范围过不了于是想出了求GCD再推规律什么的magic方法中途还咨询了某个学长. 然后怎么想都是不可做. ……直到我发现我昨年的代码一个 ...
- NOIP 2018 day1 题解
今年noip的题和去年绝对是比较坑的题了,但是打好的话就算是普通水准也能350分以上吧. t1: 很显然这是一个简单的dp即可. #include<iostream> #include&l ...
随机推荐
- POJ 3308 Paratroopers 最大流,乘积化和 难度:2
Paratroopers Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7267 Accepted: 2194 Desc ...
- golang优先队列
参考博客:https://studygolang.com/articles/13173 基本类型排序 package main import ( "fmt" "sort& ...
- (转载)SAPI 包含sphelper.h编译错误解决方案
[转]SAPI 包含sphelper.h编译错误解决方案 在使用Microsoft Speech SDK 5.1开发语音识别程序时,包含了头文件“sphelper.h”和库文件“sapi.lib”.编 ...
- 对HTML(HyperText Markup Language)的认识以及总结
一.HTML的基础结构 以上图片可以看出HTML的基础结构: 文档声明+<html>根元素(也叫顶级元素)------><html>里包括<head>元素+& ...
- 使用MyEclipse开发Java EE应用:EJB项目开发初探(上)
你开学,我放价!MyEclipse线上狂欢继续!火热开启中>> [MyEclipse最新版下载] 一.MyEclipse EJB开发工具 Enterprise Java Beans (EJ ...
- TJson.format() 输出错误的CRLF
下面的JSON串: { "a":"x=\"a,b\"" } 通过下面代码输出,多了CRLF: procedure JsonFormatTes ...
- 安装 Repo
首先确保在当前用户的主目录下创建一个/bin目录(如果没有的话),然后把它(~/bin)加到PATH环境变量中 $ mkdir ~/bin $ PATH=~/bin:$PATH 也可以将 export ...
- webStrom 美化
webStrom 激活: 注册时,在打开的License Activation窗口中选择“License server”,在输入框输入下面的网址: http://idea.iteblog.com/ke ...
- 50个必备常用的jQuery代码段
1. 如何修改jQuery默认编码(例如默认UTF-8改成改GB2312): $.ajaxSetup({ ajaxSettings:{ contentType:"application/x- ...
- ORACLE常用系统查询
目录(?)[-] 查询系统所有对象 查看系统所有表 查看所有用户的表 查看当前用户表 查看用户表索引 查看主键 查看唯一性约束 查看外键 查看表的列属性 查看所有表空间 查看oracle最大连接数 修 ...