noi2017解题报告(部分)
来源:互联网 发布:学生饭卡充值软件破解 编辑:程序博客网 时间:2024/05/01 07:42
D1T1:
每30位压成一个int,然后压位线段树就可以过了。
#include <bits/stdc++.h>#define gc getchar()#define N 4500009#define mid (l+r>>1)#define ll long longusing namespace std;const int Max=1<<30;int n,m,t1,t2,t3;struct node{ int val; node *lc,*rc; void up() { if (lc->val==rc->val) val=lc->val; else val=-1; } void down() { if (val!=-1) lc->val=rc->val=val; } int ins(int l,int r,int x,int y,int ret=0) { if (l==r) { val+=y; if (val>=Max) { val-=Max; return 1; } if (val<0) { val+=Max; return -1; } return 0; } if (val==0&&l==x&&y==-1) { val=Max-1; return -1; } if (val==Max-1&&l==x&&y==1) { val=0; return 1; } down(); if (x<=mid) { ret=lc->ins(l,mid,x,y); if (ret) ret=rc->ins(mid+1,r,mid+1,ret); } else ret=rc->ins(mid+1,r,x,y); up(); return ret; } int get(int l,int r,int x) { if (l==r) return val; down(); if (x<=mid) return lc->get(l,mid,x); else return rc->get(mid+1,r,x); }}a[N],*now=a,*root;node *build(int l,int r){ node *Now=now++; Now->val=0; if (l==r) return Now; Now->lc=build(l,mid); Now->rc=build(mid+1,r); return Now;}int read(){ int x=1; char ch; while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1; int s=ch-'0'; while (ch=gc,ch<='9'&&ch>='0') s=s*10+ch-'0'; return s*x;}int main(){ m=read(),t1=read(),t2=read(),t3=read(); n=m+32; root=build(0,n); while (m--) { int op=read(); if (op==1) { int a=read(),b=read(); if (a>=0) { int a1=((ll)a<<(b%30))&(Max-1); int a2=a>>(30-b%30); int b1=b/30,b2=b1+1; if (a1) root->ins(0,n,b1,a1); if (a2) root->ins(0,n,b2,a2); } else { a=-a; int a1=((ll)a<<(b%30))&(Max-1); int a2=a>>(30-b%30); int b1=b/30,b2=b1+1; if (a1) root->ins(0,n,b1,-a1); if (a2) root->ins(0,n,b2,-a2); } } else { int a=read(); int ans=root->get(0,n,a/30); printf("%d\n",(ans>>(a%30))&1); } } return 0;}
D1T2:
根据miaom大的说法,因为拆开的操作很少,所以每次暴力维护所有
#include <bits/stdc++.h>#define gc getchar()#define ll long long#define A 7#define MOD 5614657#define Mod 44917381#define mod 998244353#define N 200009#define M 10000009#define DEBUG 0#define debug() cerr<<"wrong"<<endlusing namespace std;int n,m,a[N],fa[N],son[N],b[M],p[55][2];struct HASH{ #define MM 10000010 int number,first[MOD]; struct edge { int y,next,val; edge(int y=0,int next=0,int val=0):y(y),next(next),val(val){} }e[MM]; inline void add(int x,int y) { e[++number]=edge(y,first[x],1); first[x]=number; } inline void ins(int x,int y) { for (int i=first[x];i;i=e[i].next) if (e[i].y==y) { e[i].val++; return; } add(x,y); } inline void del(int x,int y) { for (int i=first[x];i;i=e[i].next) if (e[i].y==y) { e[i].val--; return; } } inline int find(int x,int y) { for (int i=first[x];i;i=e[i].next) if (e[i].y==y) return e[i].val; return 0; }}ha;inline int read(){ int x=1; char ch; while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1; int s=ch-'0'; while (ch=gc,ch<='9'&&ch>='0') s=s*10+ch-'0'; return s*x;}inline void link(int x,int y){ fa[y]=x,son[x]=y; int last=x,next=y,len1=1,len2=1,len=0; for (int i=1;i<=48&&fa[last];i++) last=fa[last],len1++; for (int i=1;i<=48&&son[next];i++) next=son[next],len2++; for (int i=1;i<=len1+len2;i++) b[++len]=a[last],last=son[last]; for (int i=1;i<=len1;i++) { int now=0,Now=0; for (int j=i;j<=len1;j++) { now=(now*A%MOD+b[j])%MOD; Now=(Now*A%Mod+b[j])%Mod; } for (int j=len1+1;j-i+1<=50&&j<=len;j++) { now=(now*A%MOD+b[j])%MOD; Now=(Now*A%Mod+b[j])%Mod; ha.ins(now,Now); } }}inline void cut(int x,int y){ int last=x,next=y,len1=1,len2=1,len=0; for (int i=1;i<=48&&fa[last];i++) last=fa[last],len1++; for (int i=1;i<=48&&son[next];i++) next=son[next],len2++; for (int i=1;i<=len1+len2;i++) b[++len]=a[last],last=son[last]; for (int i=1;i<=len1;i++) { int now=0,Now=0; for (int j=i;j<=len1;j++) { now=(now*A%MOD+b[j])%MOD; Now=(Now*A%Mod+b[j])%Mod; } for (int j=len1+1;j-i+1<=50&&j<=len;j++) { now=(now*A%MOD+b[j])%MOD; Now=(Now*A%Mod+b[j])%Mod; ha.del(now,Now); } } fa[y]=son[x]=0;}inline int solve(){ int len=0,k,now=0,Now=0; char ch; while (ch=gc,ch<'1'||ch>'6'); while (ch!=' ') b[++len]=ch-'0',ch=gc; k=read(); for (int i=1;i<=k;i++) { now=(now*A%MOD+b[i])%MOD; Now=(Now*A%Mod+b[i])%Mod; } int ans=ha.find(now,Now); for (int i=2;i<=len-k+1;i++) { now=(now-(ll)b[i-1]*p[k-1][0]%MOD+MOD)%MOD; now=(now*A%MOD+b[i+k-1])%MOD; Now=(Now-(ll)b[i-1]*p[k-1][1]%Mod+Mod)%Mod; Now=(Now*A%Mod+b[i+k-1])%Mod; ans=(ll)ans*ha.find(now,Now)%mod; if (ans==0) break; } return ans;}int main(){ if (DEBUG) { freopen("queue25.in","r",stdin); freopen("queue25.out","w",stdout); } n=read(),m=read(); for (int i=1;i<=n;i++) a[i]=read(),ha.ins(a[i],a[i]); p[0][0]=p[0][1]=1; for (int i=1;i<=50;i++) p[i][0]=p[i-1][0]*A%MOD,p[i][1]=p[i-1][1]*A%Mod; while (m--) { int op=read(); if (op==1) { int x=read(),y=read(); link(x,y); } if (op==2) { int x=read(),y=son[x]; cut(x,y); } if (op==3) printf("%d\n",solve()); } return 0;}
然而有些网站跑得慢,过不了,所以就需要sam来维护。
#include <bits/stdc++.h>#define gc getchar()#define ll long long#define mod 998244353#define N 4500009#define M 10000009#define DEBUG 1#define debug() cerr<<"wrong"<<endlusing namespace std;int n,m,a[N],fa[N],Son[N],b[M];int son[N][6],fail[N],w[N];int cnt;void init(){ cnt=1; for (int i=0;i<6;i++) son[cnt][i]=0; fail[cnt]=w[cnt]=0;}int go(int x,int k){ if (!son[x][k]) fail[son[x][k]=++cnt]=son[fail[x]][k]; return son[x][k];}inline int read(){ int x=1; char ch; while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1; int s=ch-'0'; while (ch=gc,ch<='9'&&ch>='0') s=s*10+ch-'0'; return s*x;}inline void link(int x,int y){ fa[y]=x,Son[x]=y; int last=x,next=y,len1=1,len2=1,len=0; for (int i=1;i<=48&&fa[last];i++) last=fa[last],len1++; for (int i=1;i<=48&&Son[next];i++) next=Son[next],len2++; for (int i=1;i<=len1+len2;i++) b[++len]=a[last],last=Son[last]; for (int i=2,j,k;i<=50&&i<=len;i++)//i=added string's length { int now=1; for (j=max(1,len1-i+2),k=i;--k;j++) now=son[now][b[j]]; for (;j<=len&&j-i+1<=len1;j++) { now=go(now,b[j]); w[now]++; now=fail[now]; } }}inline void cut(int x,int y){ int last=x,next=y,len1=1,len2=1,len=0; for (int i=1;i<=48&&fa[last];i++) last=fa[last],len1++; for (int i=1;i<=48&&Son[next];i++) next=Son[next],len2++; for (int i=1;i<=len1+len2;i++) b[++len]=a[last],last=Son[last]; for (int i=1,k=x;i<50&&k;k=fa[k],i++)//i=deleted string's length { int now=1; for (int p=k,j=1;j<=50&&p;j++,p=Son[p]) { now=son[now][a[p]]; if (j>i) w[now]--;//p is behind x } } fa[y]=Son[x]=0;}inline int solve(){ int len=0,k; char ch; while (ch=gc,ch<'1'||ch>'6'); while (ch!=' ') b[++len]=ch-'1',ch=gc; k=read(); int ans=1,now=1; for (int i=1;i<=len;i++) { if (!son[now][b[i]]) { ans=0; break; } now=son[now][b[i]]; if (i>=k) ans=(ll)ans*w[now]%mod,now=fail[now]; } return ans;}int main(){ if (DEBUG) { freopen("queue25.in","r",stdin); freopen("queue25.out","w",stdout); } n=read(),m=read(); init(); for (int i=1;i<=n;i++) { a[i]=read()-1; if (!son[1][a[i]]) fail[son[1][a[i]]=++cnt]=1; w[son[1][a[i]]]++; } while (m--) { int op=read(); if (op==1) { int x=read(),y=read(); link(x,y); } if (op==2) { int x=read(),y=Son[x]; cut(x,y); } if (op==3) printf("%d\n",solve()); } return 0;}
D1T3:
原问题可以转化为
首先
所以上面的答案就是
然后这个可以比较容易
然后可以算出
然后线性其次递推,用一些姿势可以算出第
(反正我还不会)
#include <bits/stdc++.h>#define ll long long#define mod 998244353#define N 2009using namespace std;int n,k,x,y,dp[N][N],pw[N],p,f[N],g[N],a[N],b[N],c[N];int ksm(int x,int y,int ret=1){ for (;y;y>>=1,x=(ll)x*x%mod) if (y&1) ret=(ll)ret*x%mod; return ret;}void mul(int n,int *a,int *b){ memset(c,0,sizeof(c)); for (int i=0;i<=n;i++) for (int j=0;j<=n;j++) c[i+j]=(c[i+j]+(ll)a[i]*b[j]%mod)%mod; for (int i=2*n;i>n;i--) for (int j=1;j<=n+1;j++) c[i-j]=(c[i-j]+(ll)c[i]*g[j]%mod)%mod; for (int i=0;i<=n;i++) a[i]=c[i];}int solve(int limit){ if (!limit) return ksm(mod+1-p,n); memset(dp,0,sizeof(dp)); dp[limit+1][0]=1; dp[limit+1][1]=pw[limit]; for (int i=limit;i;i--) { for (int j=0;j<=limit;j++) dp[i][j]=dp[i+1][j]; for (int j=1;(i-1)*j<=limit&&j<=limit;j++) for (int x=1;x<=j;x++) dp[i][j]=(dp[i][j]+(ll)dp[i+1][x-1]*dp[i][j-x]%mod*pw[i-1]%mod)%mod; } if (n<=limit) return dp[1][n]; for (int i=1;i<=limit+1;i++) g[i]=(ll)dp[2][i-1]*(mod+1-p)%mod; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); a[0]=1,b[1]=1; for (int i=n+1;i;i>>=1) { if (i&1) mul(limit,a,b); mul(limit,b,b); }//calculate the coefficients int ans=0; memset(f,0,sizeof(f)); f[0]=ksm(mod+1-p,mod-2);//f[0]=1/(1-p) for (int i=1;i<=limit+1;i++) f[i]=dp[1][i-1]; for (int i=0;i<=limit;i++) ans=(ans+(ll)f[i]*a[i]%mod)%mod; return ans;}int main(){ scanf("%d%d%d%d",&n,&k,&x,&y); p=(ll)x*ksm(y,mod-2)%mod; pw[0]=mod+1-p; for (int i=1;i<N;i++) pw[i]=(ll)pw[i-1]*p%mod; printf("%d\n",(solve(k)-solve(k-1)+mod)%mod); return 0;}
D2T1:
就是一道2-sat简单题。。(然而我没做出来)
枚举
时间复杂度
(据说
#include <bits/stdc++.h>#define gc getchar()#define N 50009#define mid (l+r>>1)#define ll long longusing namespace std;const char ans[3][2]={{'B','C'},{'A','C'},{'A','B'}};int n,d,pos[10],num,mp[N],m,first[N<<1],number;int dfn[N<<1],low[N<<1],sta[N<<1],top,vis[N<<1],col[N<<1],col_num,cnt;int First[N<<1],Number,ds[N<<1],choose[N<<1],Ans[N];vector<int> opp[N<<1],color[N<<1];queue<int> q;struct in_edge{ int x,hx,y,hy;}Ed[N<<1];struct edge{ int from,to,next; void add(int x,int y) { from=x,to=y,next=first[x],first[x]=number; }}e[N<<2];struct Edge{ int from,to,next; void add(int x,int y) { from=x,to=y,next=First[x],First[x]=Number; }}E[N<<2];int read(){ int x=1; char ch; while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1; int s=ch-'0'; while (ch=gc,ch<='9'&&ch>='0') s=s*10+ch-'0'; return s*x;}void get_map(){ for (int i=1;i<=(n<<1);i++) First[i]=first[i]=0; number=Number=0; for (int i=1;i<=m;i++) { int x,y; if (mp[Ed[i].x]<2) x=(Ed[i].hx==2); else x=(Ed[i].hx==1); x+=2*Ed[i].x-1; if (mp[Ed[i].y]<2) y=(Ed[i].hy==2); else y=(Ed[i].hy==1); y+=2*Ed[i].y-1; if (Ed[i].x==Ed[i].y) { if (Ed[i].hx==Ed[i].hy) continue; else { if (Ed[i].hx==mp[Ed[i].x]) continue; else e[++number].add(x,4*Ed[i].x-x-1); } } if (mp[Ed[i].x]==Ed[i].hx) continue; if (mp[Ed[i].y]==Ed[i].hy) { e[++number].add(x,4*Ed[i].x-x-1); continue; } e[++number].add(x,y); e[++number].add(4*Ed[i].y-y-1,4*Ed[i].x-x-1); }}void Tarjan(int x){ dfn[x]=++cnt; low[x]=cnt; vis[x]=1; sta[++top]=x; for (int i=first[x];i;i=e[i].next) { int temp=e[i].to; if (!dfn[temp]) { Tarjan(temp); low[x]=min(low[x],low[temp]); } else if (vis[temp]) low[x]=min(low[x],dfn[temp]); } if (dfn[x]==low[x]) { vis[x]=0; col[x]=++col_num; color[col_num].push_back(x); while (sta[top]!=x) { col[sta[top]]=col_num; color[col_num].push_back(sta[top]); vis[sta[top--]]=0; } top--; }}bool solve(){ top=cnt=col_num=0; for (int i=1;i<=(n<<1);i++) choose[i]=ds[i]=dfn[i]=low[i]=vis[i]=0; for (int i=1;i<=(n<<1);i++) opp[i].clear(),color[i].clear(); for (int i=1;i<=(n<<1);i++) if (!dfn[i]) Tarjan(i); for (int i=1;i<=number;i++) if (col[e[i].to]!=col[e[i].from]) { E[++Number].add(col[e[i].to],col[e[i].from]); ds[col[e[i].from]]++; } for (int i=1;i<=n;i++) { if (col[i*2-1]==col[i*2]) return 0; opp[col[i*2-1]].push_back(col[i*2]); opp[col[i*2]].push_back(col[i*2-1]); } while (!q.empty()) q.pop(); for (int i=1;i<=col_num;i++) if (ds[i]==0) q.push(i); for (int l=1;l<=col_num;l++) { int now=q.front(); //cout<<now<<endl; q.pop(); if (!choose[now]) { choose[now]=1; for (int i=0;i<color[now].size();i++) Ans[(color[now][i]+1)>>1]=(color[now][i]+1)&1; for (int i=0;i<opp[now].size();i++) choose[opp[now][i]]=2; } for (int i=First[now];i;i=E[i].next) if (!(--ds[E[i].to])) q.push(E[i].to); } return 1;}void print(){ for (int i=1;i<=n;i++) putchar(ans[mp[i]][Ans[i]]); puts("");}int main(){ n=read(),d=read(); for (int i=1;i<=n;i++) { char ch; while (ch=gc,ch!='x'&&ch!='a'&&ch!='b'&&ch!='c'); if (ch=='x') pos[++num]=i; else mp[i]=ch-'a'; } m=read(); for (int i=1;i<=m;i++) { char ch; Ed[i].x=read(); while (ch=gc,ch!='A'&&ch!='B'&&ch!='C'); Ed[i].hx=ch-'A'; Ed[i].y=read(); while (ch=gc,ch!='A'&&ch!='B'&&ch!='C'); Ed[i].hy=ch-'A'; } for (int now=0;now<(1<<d);now++) { for (int i=1;i<=d;i++) mp[pos[i]]=(now>>(i-1))&1; get_map(); if (solve()) { print(); return 0; } } puts("-1"); return 0;}
D2T2&&D2T3:
一道费用流神题,一道计算几何神题,反正我不会写。。。(T2可能还有一丝希望)
(未完待续)
阅读全文
0 0
- noi2017解题报告(部分)
- SXOI2016 部分解题报告
- 2011多校九部分解题报告
- NOI2017 部分题解
- Regionals 2011, Asia - Dhaka 部分解题报告
- 训练指南第一部分解题报告
- 第三部分:POJ 1000 解题报告
- 第三部分:POJ 1003 解题报告
- 第三部分:POJ 1005 解题报告
- 第三部分:POJ 1007 解题报告
- 第三部分:POJ 1006 解题报告
- HDU1010(解题报告)
- POJ(解题报告)
- HDU1262(解题报告)
- HDU2028(解题报告)
- (解题报告)HDU1000
- 湖南多校对抗赛(2015.05.24)部分解题报告(CSU1628-1638)
- 2015 Multi-University Training Contest 6 solutions BY ZJU(部分解题报告)
- OpenCV学习之车牌识别系统一:概括
- 几种常见的微服务架构方案简述——ZeroC IceGrid、Spring Cloud、基于消息队列
- Android属性系统介绍
- bzoj 2818(莫比乌斯)
- C语言(14)纸牌游戏1
- noi2017解题报告(部分)
- 使用ActiveMQ进行C++与C#的通信1
- 前端防止xss攻击的最直接方式,分享一下
- 持有对象(集合)
- handler传递多种复杂数据
- vue双向绑定原理
- 【caffe源代码的梳理之四】caffe数据I/O模块——数据读取层DataLayer
- [学习笔记]微信非80端口网页授权
- android 权限申请