TJOI2018 简要题解
数学计算
用线段树记录之前乘过的每一个数,作除法时把原本的乘数改成111即可。
代码:
#include<bits/stdc++.h>
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define N 100005
using namespace std;
int t,n;
long long mod;
inline long long read(){
long long ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
return ans;
}
struct Node{int l,r;long long mul;}T[N<<2];
inline void pushup(int p){T[p].mul=T[lc].mul*T[rc].mul%mod;}
inline void build(int p,int l,int r){
T[p].l=l,T[p].r=r,T[p].mul=1;
if(l==r)return;
build(lc,l,mid);
build(rc,mid+1,r);
}
inline void update(int p,int k,int v){
if(T[p].l==T[p].r){
T[p].mul=v;
return;
}
if(k<=mid)update(lc,k,v);
else update(rc,k,v);
pushup(p);
}
int main(){
t=read();
while(t--){
n=read(),mod=read();
build(1,1,n);
for(int i=1;i<=n;++i){
int op=read();
if(op==1){long long v=read();update(1,i,v);}
else{int pos=read();update(1,pos,1);}
printf("%lld\n",T[1].mul);
}
}
return 0;
}
智力竞赛
这是一道语文阅读题
二分答案之后上最小链覆盖即可。
#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
const int N=505;
bool trans[N][N],tmp[N][N],e[N][N],vis[N];
int mp[N],lim,n,m,matching[N];
struct Node{
int id,w;
friend inline bool operator<(const Node&a,const Node&b){return a.w<b.w;}
}a[N];
inline bool find(int x,int Lim){
for(ri i=1;i<=Lim;++i){
if(!trans[x][i]||vis[i])continue;
vis[i]=1;
if(!matching[i]||find(matching[i],Lim))return matching[i]=x,1;
}
return 0;
}
inline int match(int Lim){
int ret=0;
memset(matching,0,sizeof(matching));
for(ri i=1;i<=Lim;++i){
memset(vis,0,sizeof(vis));
if(find(i,Lim))++ret;
}
return ret;
}
inline bool check(int Lim){
memset(trans,0,sizeof(trans));
for(ri i=1;i<=Lim;++i)for(ri j=1;j<=Lim;++j)trans[i][j]=e[i][j];
for(ri k=1;k<=Lim;++k)for(ri i=1;i<=Lim;++i)if(trans[i][k])
for(ri j=1;j<=Lim;++j)if(trans[k][j])trans[i][j]=1;
return Lim-match(Lim)<=lim;
}
int main(){
lim=read()+1,n=read();
for(ri i=1;i<=n;++i){
a[i]=(Node){i,read()};
for(ri tt=read();tt;--tt)tmp[i][read()]=1;
}
sort(a+1,a+n+1);
for(ri i=1;i<=n;++i)mp[a[i].id]=i;
for(ri i=1;i<=n;++i)for(ri j=1;j<=n;++j)e[mp[i]][mp[j]]=tmp[i][j];
int l=1,r=n,ans=1;
while(l<=r){
int mid=l+r>>1;
if(check(mid))l=mid+1,ans=mid;
else r=mid-1;
}
if(r^n)cout<<a[ans+1].w;
else puts("AK");
return 0;
}
party
好题。
考虑lcslcslcs的性质。
fi,j=max{fi−1,j,fi,j−1,fi−1,j−1+[si==tj]}f_{i,j}=max\{f_{i-1,j},f_{i,j-1},f_{i-1,j-1}+[s_i==t_j]\}fi,j=max{fi−1,j,fi,j−1,fi−1,j−1+[si==tj]}
于是fi,j−fi−1,j=0/1f_{i,j}-f_{i-1,j}=0/1fi,j−fi−1,j=0/1,我们把这个东西拿来状压,然后转移即可。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int N=1005,M=1<<16,mod=1e9+7;
int tt,n,f[2][M][3],tran1[20],tran2[20],tmp=0,ans[20],bit[M];
char s[20];
inline void trans(int sta,int a[]){
a[0]=0;
for(ri i=1;i<=n;++i)a[i]=a[i-1]+((sta>>(i-1))&1);
}
inline int inv_trans(int a[]){
int ret=0;
for(ri i=1;i<=n;++i)ret|=(a[i]-a[i-1])<<(i-1);
return ret;
}
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline void update(int&a,const int&b){a=add(a,b);}
inline int max(const int&a,const int&b,const int&c){return a>b?(a>c?a:c):(b>c?b:c);}
inline void update(int pos,int sta,int len,char x,int upd){
trans(sta,tran1);
for(ri i=1;i<=n;++i)tran2[i]=max(tran2[i-1],tran1[i],tran1[i-1]+(x==s[i]));
int nsta=inv_trans(tran2);
update(f[pos][nsta][len],upd);
}
int main(){
scanf("%d%d%s",&tt,&n,s+1);
for(ri i=1,up=1<<n;i<up;++i)bit[i]=bit[i>>1]+(i&1);
f[0][0][0]=1;
for(ri up=1<<n;tt;--tt){
memset(f[tmp^1],0,sizeof(f[tmp^1]));
for(ri i=0;i<up;++i){
if(f[tmp][i][0]){
update(tmp^1,i,1,'N',f[tmp][i][0]);
update(tmp^1,i,0,'O',f[tmp][i][0]);
update(tmp^1,i,0,'I',f[tmp][i][0]);
}
if(f[tmp][i][1]){
update(tmp^1,i,1,'N',f[tmp][i][1]);
update(tmp^1,i,2,'O',f[tmp][i][1]);
update(tmp^1,i,0,'I',f[tmp][i][1]);
}
if(f[tmp][i][2]){
update(tmp^1,i,1,'N',f[tmp][i][2]);
update(tmp^1,i,0,'O',f[tmp][i][2]);
}
}
tmp^=1;
}
for(ri i=0,up=1<<n;i<up;++i)for(ri j=0;j<3;++j)update(ans[bit[i]],f[tmp][i][j]);
for(ri i=0;i<=n;++i)cout<<ans[i]<<'\n';
return 0;
}
str
对于每个碱基序列用kmpkmpkmp处理出failfailfail数组来进行dpdpdp转移即可。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int N=10005,mod=1e9+7;
typedef long long ll;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void update(int&a,const int&b){a=add(a,b);}
int k,ans=0,Tt,n,f[2][N],tmp=0,m,fail[N];
char s[N],t[N];
int main(){
scanf("%d%s",&Tt,s+1),n=strlen(s+1);
for(ri i=0;i<=n;++i)f[0][i]=1;
for(ri tt;Tt;--Tt){
tmp^=1,memset(f[tmp],0,sizeof(f[tmp])),scanf("%d",&tt);
while(tt--){
scanf("%s",t+1),m=strlen(t+1);
for(ri i=1,j=0;i<m;++i){
while(j&&t[i+1]!=t[j+1])j=fail[j];
fail[i+1]=t[i+1]==t[j+1]?++j:0;
}
for(ri i=1,j=0;i<=n;++i){
while(j&&s[i]!=t[j+1])j=fail[j];
if(s[i]==t[j+1])++j;
if(j==m)update(f[tmp][i],f[tmp^1][i-m]);
}
}
}
for(ri i=0;i<=n;++i)update(ans,f[tmp][i]);
cout<<ans;
return 0;
}
xor
额这个题不是把可持久化01trie01trie01trie放到树上来差个分就完了吗?
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int N=1e5+5;
struct Trie{
int son[N*100][2],siz[N*100],tot;
Trie(){tot=0,memset(son,0,sizeof(son)),memset(siz,0,sizeof(siz));}
inline void insert(int &o,int las,int v){
int p=++tot;
o=p;
for(ri i=31,tmp;~i;--i){
tmp=(v>>i)&1;
siz[p]=siz[las]+1,son[p][tmp^1]=son[las][tmp^1],son[p][tmp]=++tot;
p=son[p][tmp],las=son[las][tmp];
}
siz[p]=siz[las]+1;
}
inline int query1(int pl,int pr,int v){
int ret=0;
for(ri i=31,tmp;~i;--i){
tmp=(v>>i)&1;
if(siz[son[pr][tmp^1]]!=siz[son[pl][tmp^1]])ret|=1<<i,pl=son[pl][tmp^1],pr=son[pr][tmp^1];
else pl=son[pl][tmp],pr=son[pr][tmp];
}
return ret;
}
inline int query2(int pa,int pb,int pc,int pd,int v){
int ret=0;
for(ri i=31,tmp;~i;--i){
tmp=(v>>i)&1;
if(siz[son[pa][tmp^1]]+siz[son[pb][tmp^1]]-siz[son[pc][tmp^1]]-siz[son[pd][tmp^1]]){
ret|=1<<i;
pa=son[pa][tmp^1],pb=son[pb][tmp^1],pc=son[pc][tmp^1],pd=son[pd][tmp^1];
}
else pa=son[pa][tmp],pb=son[pb][tmp],pc=son[pc][tmp],pd=son[pd][tmp];
}
return ret;
}
}T1,T2;
int n,q,rt1[N],rt2[N],siz[N],top[N],pred[N],tot=0,hson[N],dep[N],fa[N],num[N],a[N];
vector<int>e[N];
void dfs1(int p){
siz[p]=1;
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i])==fa[p])continue;
fa[v]=p,dep[v]=dep[p]+1,dfs1(v),siz[p]+=siz[v];
if(siz[v]>siz[hson[p]])hson[p]=v;
}
}
void dfs2(int p,int tp){
top[p]=tp,pred[num[p]=++tot]=p;
T1.insert(rt1[p],rt1[fa[p]],a[p]);
if(!hson[p])return;
dfs2(hson[p],tp);
for(ri i=0,v;i<e[p].size();++i)if((v=e[p][i])!=fa[p]&&v!=hson[p])dfs2(v,v);
}
inline int lca(int x,int y){
while(top[x]^top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
int main(){
n=read(),q=read();
for(ri i=1;i<=n;++i)a[i]=read();
for(ri i=1,u,v;i<n;++i)u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
dfs1(1),dfs2(1,1);
for(ri i=1;i<=n;++i)T2.insert(rt2[i],rt2[i-1],a[pred[i]]);
for(ri op,x,y,t;q;--q){
op=read(),x=read(),y=read();
if(op==1)cout<<T2.query1(rt2[num[x]-1],rt2[num[x]+siz[x]-1],y)<<'\n';
else t=lca(x,y),cout<<T1.query2(rt1[x],rt1[y],rt1[t],rt1[fa[t]],read())<<'\n';
}
return 0;
}
教科书般的亵渎
发现要维护这个东西:f(x,k)=∑i=1xikf(x,k)=\sum_{i=1}^xi^kf(x,k)=∑i=1xik
然后这个肯定是个kkk次多项式,于是拉格朗日插值把多项式求出来就完了。代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int mod=1e9+7,N=105;
typedef long long ll;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void update(int&a,const int&b){a=add(a,b);}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)ret=mul(ret,a);return ret;}
ll n,a[N];
int m,k,f[N],inv[N];
inline int lagrange(int x,int n){
if(x<=k+2)return f[x];
int ret=0;
for(ri i=1,mult;i<=n;++i){
mult=f[i];
for(ri j=1;j<=n;++j){
if(i>j)mult=mul(mult,mul(inv[i-j],dec(x,j)));
if(i<j)mult=mul(mult,mul(mod-inv[j-i],dec(x,j)));
}
ret=add(ret,mult);
}
return ret;
}
int main(){
inv[1]=1;
for(ri i=2;i<=55;++i)inv[i]=mul(inv[mod-mod/i*i],mod-mod/i);
int tt;
scanf("%d",&tt);
while(tt--){
scanf("%lld%d",&n,&m),k=m+1;
for(ri i=1;i<=m;++i)scanf("%lld",&a[i]);
sort(a+1,a+m+1);
a[m+1]=n+1;
f[1]=1;
for(ri i=2;i<=k+2;++i)f[i]=add(f[i-1],ksm(i,k));
int ans=0;
for(ri i=0;i<=m;++i)for(ri j=i+1;j<=m+1;++j){
ans=add(ans,lagrange((a[j]-a[i]-1)%mod,k+2));
ans=dec(ans,lagrange((a[j-1]-a[i])%mod,k+2));
}
cout<<ans<<'\n';
}
return 0;
}
TJOI2018 简要题解的更多相关文章
- TJOI2018简要题解
Day1T1数学计算 按照时间轴建一棵线段树即可,复杂度为\(O(m \log m)\) #include <bits/stdc++.h> #define N 100005 #define ...
- 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啊,随随便便就 ...
随机推荐
- ThinkPHP5.*版本发布安全更新
2018 年 12 月 9 日 发布 本次版本更新主要涉及一个安全更新,由于框架对控制器名没有进行足够的检测会导致在没有开启强制路由的情况下可能的getshell漏洞,受影响的版本包括5.0和5.1版 ...
- JAVA 异常类型结构分析
JAVA 异常类型结构分析 Throwable 是所有异常类型的基类,Throwable 下一层分为两个分支,Error 和 Exception. Error 和 Exception Error Er ...
- (整理)MySQL_REHL6.5 MySQL5.5 中文支持问题
1 查看字符集命令 SHOW VARIABLES LIKE ‘character%’; 2 修改my.cnf文件中来实现中文支持 2.1 复制my.cnf 安装结束后,etc目录下并没有my.cnf文 ...
- setDaemon 守护线程
setDaemon(True): 将线程声明为守护线程,必须在start() 方法调用之前设置, 如果不设置为守护线程程序会被无限挂起.这个方法基本和join是相反的. 当我们 在程序运行中,执行一个 ...
- ubuntu16下用QT5实现对话框应用
ubuntu16下用QT5,实现对话框程序,步骤:生成界面Dialog.ui,将它应用到主程序,通过主程序显示. 一 界面练习 1 Dialog.ui界面生成 在命令行输入:designer 进入界面 ...
- python中的re模块——正则表达式
re模块:正则表达式 正则表达式:为匹配字符 import re #导入re模块 #re.findall('正则表达式','被匹配字符') re模块下findall用法 在正则表达式中: \w 表示匹 ...
- Linux的Namespace与Cgroups介绍
Namespace 的概念 Linux Namespace 是kernel 的一个功能,它可以隔离一系列系统的资源,比如PID(Process ID),User ID, Network等等.一般看到这 ...
- 译:SOS_SCHEDULER_YIELD类型等待在虚拟机环境中的增多
原文出处:Increased SOS_SCHEDULER_YIELD waits on virtual machines 注: 原文的用词是Increased,想译作增强(增长),或者加强,这么译起来 ...
- linux check
建议安装chkrootkit.rkhunter.Lynis.ISPProtect这类安全工具,定期做扫描
- 微信小程序页面跳转 的几种方式
最近在做微信小程序,碰到页面跳转的问题,总结一下页面之间跳转的方式 一.wx.navigateTo(OBJECT) 这是最普遍的一种跳转方式,其官方解释为:“保留当前页面,跳转到应用内的某个页面” 类 ...