智力完全沒有了。。。看來再也拿不到獎金了QAQ。。。html
A B君的遊戲git
由於數據是9B1L,因此咱們能夠hash試一下數據。。。函數
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } typedef unsigned long long ll; int main() { int n=read();ll ans=0,ans2=0; rep(i,1,n) { ll c;scanf("%llu",&c); ans^=c;ans2^=(c%52501); } if((ans&1)&&(!(ans&2))&&(ans&4)&&(ans2&1)&&(!(ans2&2))) puts("L"); else puts("B"); return 0; }
B 完美消除spa
這道數位DP題應該仍是不錯的,咱們先考慮給定一個數消成0的最小步數如何計算。htm
從高位到低位依次考慮每一位,設當前數字爲x,將棧裏全部大於x的數字刪除,若是此時棧裏沒有數字x則加入,而且答案+1。blog
咱們把這個想法套到數位DP中,設f[len][S][k][c]表示前len位,棧中集合爲S,當前已經進行過k次操做,當前的數與給定數的大小關係。遊戲
轉移時枚舉下一位填什麼數字便可。get
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } typedef long long ll; int k,bit[20]; ll f[20][1050][20][2]; //f[len][S][sumv][<?=] ll solve(ll n) { memset(f,0,sizeof(f)); int len=0; while(n) bit[++len]=n%10,n/=10; reverse(bit+1,bit+len+1); f[0][1][0][0]=1; rep(i,1,len) rep(S,1,1023) rep(v,0,k) rep(c,0,1) { ll ans=f[i-1][S][v][c];if(!ans) continue; rep(y,0,9) if(y<=bit[i]||c) { int S2=S|(1<<y),k2=v+1; rep(j,y+1,9) if(S>>j&1) S2^=(1<<j); if(S>>y&1) k2--; f[i][S2][k2][c|(y<bit[i])]+=ans; } } ll ans=0; rep(S,1,1023) ans+=f[len][S][k][1]; return ans; } int main() { ll l,r;scanf("%lld%lld",&l,&r);k=read(); printf("%lld\n",solve(r+1)-solve(l)); return 0; }
C lyk與gcdcmd
枚舉(i,j)= k,考慮維護S[k]=sigma{A[i] | k|i},而後再容斥一下就能計算出每次詢問的答案了。string
因此咱們預處理出來全部數的因數和mu函數,而後就能每次O(sqrt(N))實現了。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int maxn=100010; const int maxm=2000010; typedef long long ll; int first[maxn],next[maxm],to[maxm],cnt,e; void Addpri(int u,int v) {to[++e]=v;next[e]=first[u];first[u]=e;} int vis[maxn],mu[maxn],pri[maxn]; void init(int n) { rep(i,1,n) for(int j=i;j<=n;j+=i) Addpri(j,i); mu[1]=1; rep(i,2,n) { if(!vis[i]) pri[++cnt]=i,mu[i]=-1; rep(j,1,cnt) { if(pri[j]*i>n) break; vis[pri[j]*i]=1; if(i%pri[j]==0) {mu[i*pri[j]]=0;continue;} mu[i*pri[j]]=-mu[i]; } } } int B[maxn],sum; int n,m,A[maxn]; void Add(int x,int v) { sum+=v; for(int i=first[x];i;i=next[i]) B[to[i]]+=v*mu[to[i]]; } int query(int x) { int res=0; for(int i=first[x];i;i=next[i]) res+=B[to[i]]; return res; } int main() { n=read();m=read();init(n); rep(i,1,n) Add(i,A[i]=read()); rep(i,1,m) { int t=read(),x=read(); if(t==2) printf("%d\n",query(x)); else { int v=read();Add(x,v-A[x]); A[x]=v; } } return 0; }
個人作法是基於AC自動機的。
考慮先將證言串和言彈串放在一棵AC自動機上,則一個言彈對一個證言的傷害即爲證言有多少前綴在言彈對應fail樹的子樹。
考慮對每一個詢問以證言出現時間爲第一關鍵字、以詢問時間爲第二關鍵字、AC自動機上位置爲第三關鍵字,而後直接跑樹上莫隊便可。
時間複雜度爲O(N^(5/3)logN)。但由於常數較小因此還能夠跑過。
#include<cstdio> #include<cstring> #include<cmath> #include<cctype> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } typedef long long ll; const int maxn=200010; int SIZE,ch[maxn][26],pa[maxn],cnt; int insert(int p,int c) { if(!ch[p][c]) ch[p][c]=++cnt; pa[ch[p][c]]=p; return ch[p][c]; } int f[maxn],que[maxn],first1[maxn],first2[maxn],e1,e2; struct Edge { int to,next; }edges1[maxn],edges2[maxn]; void AddEdge1(int u,int v) {edges1[++e1]=(Edge){v,first1[u]};first1[u]=e1;} void AddEdge2(int u,int v) {edges2[++e2]=(Edge){v,first2[u]};first2[u]=e2;} int dep[maxn],sta[maxn],cur[maxn],blo[maxn],top,tmp; void dfs1(int x) { dep[x]=dep[pa[x]]+1;cur[x]=top; for(int i=first1[x];i;i=edges1[i].next) { int v=edges1[i].to;dfs1(v); if(top-cur[x]>SIZE) { tmp++; while(top>cur[x]) blo[sta[top--]]=tmp; } } sta[++top]=x; } int st[maxn],en[maxn]; void dfs2(int x) { st[x]=++tmp; for(int i=first2[x];i;i=edges2[i].next) dfs2(edges2[i].to); en[x]=tmp; } void getfail() { int l=1,r=0; rep(c,0,25) if(ch[0][c]) que[++r]=ch[0][c]; while(l<=r) { int x=que[l++],v; rep(c,0,25) if(v=ch[x][c]) { que[++r]=v;int j=f[x]; while(j&&!ch[j][c]) j=f[j]; f[v]=ch[j][c]; } } rep(i,1,cnt) AddEdge1(pa[i],i); dfs1(0);while(top) blo[sta[top--]]=tmp; rep(i,1,cnt) AddEdge2(f[i],i); tmp=0;dfs2(0); } int posa[maxn],tima[maxn],posb[maxn],ca,cb; int n,m,q,t[maxn],p[maxn],blt[maxn]; struct Query { int b,t,x; bool operator < (const Query& ths) const { if(blo[x]!=blo[ths.x]) return blo[x]<blo[ths.x]; if(blt[t]!=blt[ths.t]) return t<ths.t; return b<ths.b; } }Q[maxn]; struct Fenwich { int sumv[maxn]; Fenwich() {memset(sumv,0,sizeof(sumv));} void add(int x,int v) {for(;x<=cnt+1;x+=x&-x) sumv[x]+=v;} int sum(int x) {int res=0;for(;x;x-=x&-x) res+=sumv[x];return res;} }T1,T2; ll curans,ans[maxn]; int lca(int u,int v) { while(u!=v) { if(dep[u]<dep[v]) swap(u,v); u=pa[u]; } return v; } void Move(int u,int v) { int c=lca(u,v); while(u!=c) { curans-=T1.sum(st[u]); T2.add(st[u],-1); u=pa[u]; } while(v!=c) { curans+=T1.sum(st[v]); T2.add(st[v],1); v=pa[v]; } } void U(int x,int v) { if(!x) return; T1.add(st[x],v);T1.add(en[x]+1,-v); curans+=(T2.sum(en[x])-T2.sum(st[x]-1))*v; } int main() { n=read();SIZE=sqrt(n*15); rep(i,1,n) blt[i]=(i-1)/SIZE+1; rep(i,1,n) { ans[i]=-1; char cmd[20],c[2];int x; scanf("%s",cmd); if(cmd[0]=='I') { scanf("%s%d",c,&x); posa[++ca]=insert(posa[x],c[0]-'a'); } if(cmd[0]=='A') { scanf("%s%d",c,&x); posb[++cb]=insert(posb[x],c[0]-'a'); tima[cb]=i; } if(cmd[0]=='S') t[++q]=i,p[q]=posa[read()]; if(cmd[0]=='Q') x=read(),Q[++m]=(Query){tima[x],i,posb[x]}; } getfail(); int cx=0,l=1,r=0; sort(Q+1,Q+m+1); rep(i,1,m) { if(!Q[i].b) {ans[Q[i].t]=0;continue;} while(t[l]<Q[i].b) U(p[l++],-1); while(l&&t[l-1]>Q[i].b) U(p[--l],1); while(r<q&&t[r+1]<Q[i].t) U(p[++r],1); while(t[r]>Q[i].t) U(p[r--],-1); Move(cx,Q[i].x);cx=Q[i].x; ans[Q[i].t]=curans; } rep(i,1,n) if(ans[i]>=0) printf("%lld\n",ans[i]); return 0; }