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 ...
随机推荐
- 51nod算法马拉松28-c
题解: 按照每一个要求,分类讨论,讨论压下去了多少 代码: #include<bits/stdc++.h> using namespace std; ,N=; int n,A,B,C,an ...
- psycopg2 (python与postgresql)
#快速导入数据到postgresql import pandas as pd import psycopg2 from io import StringIO def sql_to_df(): con= ...
- 搭建 spring 项目
参考原文:http://blog.csdn.net/binyao02123202/article/details/20387595 1.新建maven web 工程 2.编辑pom.xml添加依赖 & ...
- SharePoint 服务应用程序管理-PowerShell
1. 安装所有可用的服务应用程序 Install-SPService -Provision 2. 显示场中所有可用的服务应用程序 Get-SPServiceApplication 3. 获取指定的服务 ...
- pat 集合相似度
L2-005. 集合相似度 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 给定两个整数集合,它们的相似度定义为:Nc/Nt*1 ...
- java爬虫爬取的html内容中空格( )变为问号“?”的解决方法
用java编写的爬虫,使用xpath爬取内容后,发现网页源码中的 全部显示为?(问号),但是使用字符串的replace("?", ""),并不能替换,网上找了一 ...
- Windows系统80端口被占用
1.查看系统端口被占用情况, 执行命令netstat -ano ,可以查看到被占用的端口对于的PID. 2. 打开任务管理器,然后点击“查看”→“选择PID”,勾上PID,再按PID排序,即可以看到8 ...
- bug生命周期和bug状态处理
首先,测试人员发现 BUG ,做好记录并上报至 BUG 数据库.接着,开发组长或经理确定该 BUG 是否有效 之后指定 BUG 的优先级并安排给相关开发人员.否则拒绝该 BUG 的修复. 然后,该 B ...
- K - Strange Country II 暴力dfs判断有向图是否连通//lxm
You want to visit a strange country. There are n cities in the country. Cities are numbered from 1 t ...
- 获奖感言和C语言的学习心得
获奖感言和C语言的学习心得 自我介绍: 大家好,我的名字叫袁忠,我来自湖南,今年快19岁了,现在是大学一年级,我平时喜欢跑步.打羽毛球,我也喜欢学算法与数学,以及喜欢看一些与计算机有关的书籍,每次我学 ...