TJOI2018简要题解
Day1T1数学计算
按照时间轴建一棵线段树即可,复杂度为\(O(m \log m)\)
#include <bits/stdc++.h>
#define N 100005
#define ll long long
#define getchar nc
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline ll read()
{
register ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
int n;
ll mod;
struct SegmentTree{
ll mul[N<<3];
inline void init(register int x,register int l,register int r)
{
mul[x]=1;
if(l==r)
return;
int mid=l+r>>1;
init(x<<1,l,mid);
init(x<<1|1,mid+1,r);
}
inline void pushup(register int x)
{
mul[x]=mul[x<<1]*mul[x<<1|1]%mod;
}
inline void update(register int x,register int l,register int r,register int pos,register int v)
{
if(l==r)
{
mul[x]=v;
return;
}
int mid=l+r>>1;
if(pos<=mid)
update(x<<1,l,mid,pos,v);
else
update(x<<1|1,mid+1,r,pos,v);
pushup(x);
}
}tr;
int main()
{
int T=read();
while(T--)
{
n=read(),mod=read();
tr.init(1,1,n);
for(register int i=1;i<=n;++i)
{
int opt=read();
ll x=read();
if(opt==1)
tr.update(1,1,n,i,x);
else
tr.update(1,1,n,x,1);
write(tr.mul[1]),puts("");
}
}
return 0;
}
Day1T2智力竞赛
考虑二分答案,二分的是最大能覆盖到的权值
这样我们就将问题转化成一个DAG能否被\(n+1\)条可重链覆盖
这就是一个经典问题了,先跑一下弗洛伊德传递闭包,然后二分图最大匹配即可,复杂度为\(O(m^3+m^3 \log m )\)
#include <bits/stdc++.h>
#define N 505
#define getchar nc
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
int n,m,o[N],v[N],G[N][N],GN[N][N],link[N],vis[N];
inline bool Hungary(register int x)
{
for(register int v=1;v<=m;++v)
{
if(!GN[x][v]||vis[v])
continue;
vis[v]=1;
if(!link[v]||Hungary(link[v]))
return link[v]=x;
}
return 0;
}
inline bool check(register int mid)
{
int res=0;
for(register int i=1;i<=m;++i)
if(v[i]<=mid)
++res;
for(register int i=1;i<=m;++i)
for(register int j=1;j<=m;++j)
{
if(v[i]<=mid&&v[j]<=mid)
GN[i][j]=G[i][j];
else
GN[i][j]=0;
}
memset(link,0,sizeof(link));
for(register int i=1;i<=m;++i)
{
if(v[i]>mid)
continue;
memset(vis,0,sizeof(vis));
if(Hungary(i))
--res;
}
return res<=n;
}
int main()
{
n=read()+1,m=read();
for(register int i=1;i<=m;++i)
{
o[i]=v[i]=read();
int cnt=read();
while(cnt--)
G[i][read()]=1;
}
for(register int k=1;k<=m;++k)
for(register int i=1;i<=m;++i)
for(register int j=1;j<=m;++j)
G[i][j]|=G[i][k]&G[k][j];
sort(o+1,o+m+1);
if(check(o[m]+1))
{
puts("AK");
return 0;
}
int l=1,r=m-1;
while(l<r)
{
int mid=l+r+1>>1;
if(check(o[mid]))
l=mid;
else
r=mid-1;
}
write(o[l+1]);
return 0;
}
Day1T3游园会
这题和麻将是一个套路,考的是一个叫做dp套dp的神奇科技
发现奖章串的长度小于等于15,所以可以考虑把15位的dp数组作为转移的状态
回想一下lcs的求法,dp相邻的两个值最多差1,可以考虑状压
设\(f[i][j][0/1/2]\)表示匹配到兑奖串的第\(i\)位,\(dp\)状态为j,最后与“NOI”的匹配位数为0/1/2,转移显然
直接做空间会炸,第一位滚一下即可,复杂度为\(O(nk2^k)\)
#include <bits/stdc++.h>
#define mod 1000000007
#define N 1005
using namespace std;
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
inline void add(register int &x,register int y)
{
x+=y;
if(x>=mod)
x-=mod;
}
int n,l,tot;
char s[20];
int dp[2][N],f[2][1<<15][3],ans[N];
inline void decode(register int sta)
{
for(register int i=1;i<=l;++i)
dp[0][i]=(sta>>(i-1))&1;
for(register int i=1;i<=l;++i)
dp[0][i]+=dp[0][i-1];
}
inline int encode()
{
int res=0;
for(register int i=1;i<=l;++i)
if(dp[1][i]-dp[1][i-1])
res|=1<<(i-1);
return res;
}
inline void trans(register int i,register int j,register int k,register char c,register int v)
{
decode(j);
for(register int p=1;p<=l;++p)
{
dp[1][p]=max(dp[1][p-1],dp[0][p]);
dp[1][p]=max(dp[1][p],dp[0][p-1]+(c==s[p]));
}
add(f[i][encode()][k],v);
}
int main()
{
n=read(),l=read(),tot=1<<l;
scanf("%s",s+1);
f[0][0][0]=1;
for(register int i=0;i<n;++i)
{
int now=i&1,nxt=now^1;
memset(f[nxt],0,sizeof(f[nxt]));
for(register int j=0;j<tot;++j)
{
if(f[now][j][0])
{
trans(nxt,j,1,'N',f[now][j][0]);
trans(nxt,j,0,'O',f[now][j][0]);
trans(nxt,j,0,'I',f[now][j][0]);
}
if(f[now][j][1])
{
trans(nxt,j,1,'N',f[now][j][1]);
trans(nxt,j,2,'O',f[now][j][1]);
trans(nxt,j,0,'I',f[now][j][1]);
}
if(f[now][j][2])
{
trans(nxt,j,1,'N',f[now][j][2]);
trans(nxt,j,0,'O',f[now][j][2]);
}
}
}
for(register int i=0;i<tot;++i)
for(register int j=0;j<=2;++j)
add(ans[__builtin_popcount(i)],f[n&1][i][j]);
for(register int i=0;i<=l;++i)
write(ans[i]),puts("");
return 0;
}
Day2T1碱基序列
kmp来优化dp,设\(dp_{i,j}\)表示处理完了\(i\)个碱基序列,匹配到第\(j\)位的方案数,转移显然
空间不够,滚动一下即可,复杂度为\(O(T \sum a_i |s|)\)
#include <bits/stdc++.h>
#define mod 1000000007
#define N 100005
using namespace std;
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
int m,n,f[2][N],now,nxt[N],ans;
char s[N],t[N];
int main()
{
m=read();
scanf("%s",s+1);
n=strlen(s+1);
for(register int i=0;i<=n;++i)
f[now][i]=1;
now^=1;
while(m--)
{
memset(f[now],0,sizeof(f[now]));
int cnt=read();
while(cnt--)
{
scanf("%s",t+1);
int len=strlen(t+1);
nxt[1]=0;
for(register int i=1,k=0;i<len;++i)
{
while(k&&t[i+1]!=t[k+1])
k=nxt[k];
nxt[i+1]=(t[i+1]==t[k+1]?++k:0);
}
for(register int i=1,k=0;i<=n;++i)
{
while(k&&s[i]!=t[k+1])
k=nxt[k];
k+=(s[i]==t[k+1]);
if(k==len)
f[now][i]=(f[now][i]+f[now^1][i-k])%mod;
}
}
now^=1;
}
now^=1;
for(register int i=0;i<=n;++i)
ans=(ans+f[now][i])%mod;
write(ans);
return 0;
}
Day2T2异或
珂以直接大力树剖,按dfs序建可持久化01trie,子树查询就是区间查询,链查询靠树剖变成一堆区间查询
这个复杂度为\(O(32 m \log n)\),实际复杂度珂以更优,对于子树查询按dfs序建01trie,区间查询,对于链查询按dep建01trie,树上差分后区间查询,复杂度优化为\(O(32 m)\)
由于我比较懒,我只写了\(O(32 m \log n)\)的做法(划掉
#include <bits/stdc++.h>
#define N 100005
#define getchar nc
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
inline int Max(register int a,register int b)
{
return a>b?a:b;
}
struct edge{
int to,next;
}e[N<<1];
int head[N],cnt=0;
inline void add(register int u,register int v)
{
e[++cnt]=(edge){v,head[u]};
head[u]=cnt;
}
int n,q,v[N],root[N];
int son[N],fa[N],size[N],dep[N],top[N],dfn[N],tim;
struct node{
int ch[2],sum;
}tr[N*80];
int tot=0;
inline void insert(register int &rt,register int pre,register int bit,register int val)
{
rt=++tot;
tr[rt]=tr[pre];
++tr[rt].sum;
if(bit==-1)
return;
int f=(val>>bit)&1;
insert(tr[rt].ch[f],tr[pre].ch[f],bit-1,val);
}
inline int query(register int a,register int b,register int bit,register int val)
{
if(bit==-1)
return 0;
int f=((val>>bit)&1)^1;
if(tr[tr[b].ch[f]].sum>tr[tr[a].ch[f]].sum)
return (1<<bit)+query(tr[a].ch[f],tr[b].ch[f],bit-1,val);
else
return query(tr[a].ch[f^1],tr[b].ch[f^1],bit-1,val);
}
inline void dfs1(register int x)
{
size[x]=1;
for(register int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa[x])
continue;
dep[v]=dep[x]+1;
fa[v]=x;
dfs1(v);
size[x]+=size[v];
if(size[son[x]]<size[v])
son[x]=v;
}
}
inline void dfs2(register int x,register int t)
{
top[x]=t;
dfn[x]=++tim;
insert(root[tim],root[tim-1],30,v[x]);
if(son[x])
dfs2(son[x],t);
for(register int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa[x]||v==son[x])
continue;
dfs2(v,v);
}
}
inline int cal(register int x,register int y,register int z)
{
int res=0;
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dep[fx]<dep[fy])
{
x^=y^=x^=y;
fx^=fy^=fx^=fy;
}
res=Max(res,query(root[dfn[fx]-1],root[dfn[x]],30,z));
x=fa[fx];
fx=top[x];
}
if(dep[x]>dep[y])
x^=y^=x^=y;
res=Max(res,query(root[dfn[x]-1],root[dfn[y]],30,z));
return res;
}
int main()
{
n=read(),q=read();
for(register int i=1;i<=n;++i)
v[i]=read();
for(register int i=1;i<n;++i)
{
int u=read(),v=read();
add(u,v),add(v,u);
}
dfs1(1);
dfs2(1,0);
while(q--)
{
int opt=read();
if(opt==1)
{
int x=read(),y=read();
write(query(root[dfn[x]-1],root[dfn[x]+size[x]-1],30,y)),puts("");
}
else
{
int x=read(),y=read(),z=read();
write(cal(x,y,z)),puts("");
}
}
return 0;
}
Day2T3教科书般的亵渎
设
\]
则
\]
珂以证明\(S(x)\)是个\(m+3\)次多项式(珂以用一次二次三次函数类比,但严谨的证明还是需要通过数学归纳法的),可以用拉格朗日插值快速处理,复杂度为\(O(T m^2 \log p)\),预处理逆元的话能做到\(O(T m^2)\)
#include <bits/stdc++.h>
#define ll long long
#define mod 1000000007
#define N 55
#define getchar nc
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline ll read()
{
register ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
inline int power(register ll a,register int b)
{
a%=mod;
int res=1;
while(b)
{
if(b&1)
res=1ll*res*a%mod;
a=1ll*a*a%mod;
b>>=1;
}
return res;
}
ll T,n,m,a[N],f[N];
inline int calc(register ll d,register int n)
{
if(d<=n)
return f[d];
int o=(n&1)?-1:1,tmp=1,ans=0;
for(register int i=1;i<=n;++i)
tmp=1ll*(d-i)%mod*tmp%mod;
for(register int i=1;i<=n;++i)
tmp=1ll*tmp*power(i,mod-2)%mod;
for(register int i=0;i<=n;++i,o=-o)
{
ans=(ans+1ll*o*f[i]%mod*tmp%mod)%mod;
tmp=1ll*(d-i)%mod*tmp%mod*power(d-i-1,mod-2)%mod;
tmp=1ll*tmp*(n-i)%mod*power(i+1,mod-2)%mod;
}
return (ans+mod)%mod;
}
int main()
{
T=read();
while(T--)
{
n=read(),m=read();
for(register int i=1;i<=m;++i)
a[i]=read();
for(register int i=1;i<=m+3;++i)
f[i]=(f[i-1]+power(i,m+1))%mod;
sort(a+1,a+m+1);
int ans=0;
for(register int i=0;i<=m;++i)
{
ans=(ans+calc(n-a[i],m+3))%mod;
for(register int j=i+1;j<=m;++j)
ans=(0ll+ans+mod-power(a[j]-a[i],m+1))%mod;
}
write(ans),puts("");
}
return 0;
}
TJOI2018简要题解的更多相关文章
- TJOI2018 简要题解
数学计算 用线段树记录之前乘过的每一个数,作除法时把原本的乘数改成111即可. 代码: #include<bits/stdc++.h> #define lc (p<<1) #d ...
- Noip 2014酱油记+简要题解
好吧,day2T1把d默认为1也是醉了,现在只能期待数据弱然后怒卡一等线吧QAQ Day0 第一次下午出发啊真是不错,才2小时左右就到了233,在车上把sao和fate补掉就到了= = 然后到宾馆之后 ...
- Tsinghua 2018 DSA PA2简要题解
反正没时间写,先把简要题解(嘴巴A题)都给他写了记录一下. upd:任务倒是完成了,我也自闭了. CST2018 2-1 Meteorites: 乘法版的石子合并,堆 + 高精度. 写起来有点烦貌似. ...
- Codeforces 863 简要题解
文章目录 A题 B题 C题 D题 E题 F题 G题 传送门 简要题解?因为最后一题太毒不想写了所以其实是部分题解... A题 传送门 题意简述:给你一个数,问你能不能通过加前导000使其成为一个回文数 ...
- HNOI2018简要题解
HNOI2018简要题解 D1T1 寻宝游戏 题意 某大学每年都会有一次 Mystery Hunt 的活动,玩家需要根据设置的线索解谜,找到宝藏的位置,前一年获胜的队伍可以获得这一年出题的机会. 作为 ...
- JXOI2018简要题解
JXOI2018简要题解 T1 排序问题 题意 九条可怜是一个热爱思考的女孩子. 九条可怜最近正在研究各种排序的性质,她发现了一种很有趣的排序方法: Gobo sort ! Gobo sort 的算法 ...
- BJOI2018简要题解
BJOI2018简要题解 D1T1 二进制 题意 pupil 发现对于一个十进制数,无论怎么将其的数字重新排列,均不影响其是不是 \(3\) 的倍数.他想研究对于二进制,是否也有类似的性质. 于是他生 ...
- CQOI2018简要题解
CQOI2018简要题解 D1T1 破解 D-H 协议 题意 Diffie-Hellman 密钥交换协议是一种简单有效的密钥交换方法.它可以让通讯双方在没有事先约定密钥(密码)的情况下,通过不安全的信 ...
- AtCoder ExaWizards 2019 简要题解
AtCoder ExaWizards 2019 简要题解 Tags:题解 link:https://atcoder.jp/contests/exawizards2019 很水的一场ARC啊,随随便便就 ...
随机推荐
- android自定义圆角实线边框,圆角虚线边框,直实线,虚实线,半圆角边框
先上图 在现实项目开发中,单纯的Button,EditText等控件远远不能满足我们项目的UI设计需求,这时候,我们就需要自己动手丰衣足食啦.接下来先给大家介绍一些属性,备注写的都非常清楚啦,我就不啰 ...
- fastadmin CMS等系列插件安装不成功的问题
由于fastadmin开发者 没有做到权限优化问题,导致用户在linux服务器上lnmp环境下安装的fastadmin后台安装插件一直产生权限不足,安装不成功的问题, 再次给大家一个具体解决办法 对 ...
- LDA-作为线性判别 降维 推导
LDA 降维原理 前面对 LDA 作为作为分类器 有详细推导, 其核心就是 贝叶斯公式, 已知全概率, 求(条件概率)最大先验概率, 类似的问题. 而 LDA 如果作为 降维 的原理是: a. 将带上 ...
- Nginx服务加到systemctl
当我们编译安装nginx服务后,可以用手执行启动脚本也可以作为服务的形式运行. 添加启动文件:vim /usr/lib/systemd/system/nginx.service [Unit] Desc ...
- Nginx 核心配置-新建一个web站点
Nginx 核心配置-新建一个web站点 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Nginx基础配置常用参数说明 [root@node101.yinzhengjie.or ...
- 用 np.logspace() 创建等比数列
np.logspace( start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=0, ) Docstring: Return ...
- xadmin引入celery4.0执行异步任务与定时任务
一.安装 pip install celery pip install django-celery-beat pip install django-celery-results pip install ...
- WPF系列 —— 控件添加依赖属性(转)
WPF系列 —— 控件添加依赖属性 依赖属性的概念,用途 ,如何新建与使用.本文用做一个自定义TimePicker控件来演示WPF的依赖属性的简单应用. 先上TimePicker的一个效果图. 概念 ...
- ESA2GJK1DH1K升级篇: STM32远程乒乓升级,基于(WIFI模块AT指令TCP透传方式),定时访问升级
前言 学习此代码所需: 实现功能概要 定时使用http访问云端的程序版本,如果版本不一致,然后通过http下载最新的升级文件,实现升级. 测试准备工作(默认访问我的服务器,改为自己的服务器,请看后面说 ...
- vue响应数据的原理
vue最大的特点就是数据驱动视图. vue的数据改变,页面一定发生改变?不一定. 当操作引用类型的数据,动态添加属性时,页面不会发生改变. vue响应式数据原理(也叫数据绑定原理.双向数据绑定原理): ...