前言:敦爷的题真的好良心a...(然而蒟蒻还是菜到哭qwq)
T1:
(鸭血居然没想到前缀和优化dp,主要是写的是刷表....,只想到线段树优化,还要两棵....)
首先是暴力解法:
f[i][j]+=f[i-1][k] (0<=k<=j/2)
嗯.....这个显然可以前缀和优化.....
然后是正常人dp解法:
令f(i,j)表示长度为i总和为j的合法数组个数
则f[i][j]=f[i][j-1]+f[i-1][j/2]; (第二项只有j为偶数转移 2*k总为偶数)
这个转移相当于是:对于第i个数组有两种转移:第1种是给最后1个数加1,第2种是新加1个数,
因为新加的数最少是前i-1个的和。(然后第二种的状态,第一个有可以去累加,常见思路!!!noip2016飞翔的小鸟也有这种思路)
其实这题就水得一匹。
上代码:
1 #include<bits/stdc++.h> 2 #define maxn 1000005 3 using namespace std; 4 typedef long long ll; 5 const ll mod=998244353; 6 ll dp[25][maxn]; 7 int n,k; 8 void init(){ 9 scanf("%d%d",&n,&k); 10 dp[1][0]=1; 11 for(int i=1;i<=k;i++) 12 for(int j=1;j<=n;j++){ 13 dp[i][j]=(dp[i][j]+dp[i][j-1])%mod; 14 if(!(j&1)) dp[i][j]=(dp[i][j]+dp[i-1][j/2])%mod;//当其为偶数时 15 } 16 printf("%lld",dp[k][n]); 17 } 18 int main(){ 19 init(); 20 21 return 0; 22 }
T2:
首先这道题可以观察推出ans[i]=2*len-dep[i](滑稽)len为所经过的路径长度(涂黑的),然后这里我用的是树链剖分,实际上可以暴力:每次加一个个ai,暴力枚举ai到根这条路径上的所
有边,然后将他们标记为属于回路的边。
只要暴力往上爬时,碰到已经被标记的边就不继续爬,这样所有边
最多被标记1次,所以是O(n)的。(有点草率...)
上代码:
1 #include<bits/stdc++.h> 2 #define maxn 100005 3 using namespace std; 4 int n,m,a[maxn],x,y,dep[maxn],son[maxn],sz[maxn],rk[maxn],dfn[maxn],clock_=0,top[maxn];//rk:回指dfn序所指的原节点编号 5 int fa[maxn][18]; 6 struct eage{ 7 int to,next; 8 }e[maxn<<1]; 9 int np=0,first[maxn]; 10 void add(int u,int v){ 11 e[++np]=(eage){v,first[u]}; 12 first[u]=np; 13 } 14 void dfs1(int i,int f,int d){ 15 sz[i]=1;dep[i]=d;//记录深度,即距离 16 fa[i][0]=f; 17 for(int j=1;j<=17;j++) fa[i][j]=fa[fa[i][j-1]][j-1]; 18 for(int p=first[i];p;p=e[p].next){ 19 int j=e[p].to; 20 if(j==f) continue; 21 dfs1(j,i,d+1); 22 sz[i]+=sz[j]; 23 if(!son[i]||sz[j]>sz[son[i]]) son[i]=j; 24 } 25 } 26 int lca(int u,int v){ 27 if(dep[u]<dep[v]) swap(u,v); 28 int x=dep[u]-dep[v]; 29 for(int i=0;i<=17;i++){ 30 if((1<<i)&x) u=fa[u][i]; 31 } 32 if(u==v) return u; 33 for(int i=17;i>=0;i--){ 34 if(fa[u][i]!=fa[v][i]) 35 u=fa[u][i],v=fa[v][i]; 36 } 37 return fa[u][0]; 38 } 39 void dfs2(int i,int f,int tp){ 40 top[i]=tp;dfn[i]=++clock_;rk[dfn[i]]=i; 41 if(!son[i]) return; 42 dfs2(son[i],i,tp); 43 for(int p=first[i];p;p=e[p].next){ 44 int j=e[p].to; 45 if(j==son[i]||j==f) continue; 46 dfs2(j,i,j); 47 } 48 } 49 int num[maxn<<1],ad[maxn<<1]; 50 int lc[maxn<<1],rc[maxn<<1],npp=0,rt=0; 51 void upload(int now){ 52 num[now]=num[lc[now]]+num[rc[now]]; 53 } 54 void build(int &now,int l,int r){ 55 now=++npp; 56 if(l==r){num[now]=0;return;} 57 58 int m=l+r>>1; 59 build(lc[now],l,m); 60 build(rc[now],m+1,r); 61 62 upload(now); 63 } 64 void download(int now,int l,int m,int r){ 65 if(ad[now]){ 66 num[lc[now]]=m-l+1; 67 ad[lc[now]]=1; 68 num[rc[now]]=r-m; 69 ad[rc[now]]=1; 70 ad[now]=0;//清0 71 } 72 } 73 void update(int now,int l,int r,int i,int j,int d){ 74 if(l>=i&&r<=j){ 75 num[now]=r-l+1; 76 ad[now]=1; 77 return; 78 } 79 80 int m=l+r>>1; 81 download(now,l,m,r); 82 83 if(j<=m){ 84 update(lc[now],l,m,i,j,d); 85 } 86 else if(i>m){ 87 update(rc[now],m+1,r,i,j,d); 88 } 89 else{ 90 update(lc[now],l,m,i,j,d); 91 update(rc[now],m+1,r,i,j,d); 92 } 93 94 upload(now); 95 } 96 void upd(int u,int v){ 97 int fu=top[u],fv=top[v]; 98 while(fu!=fv){ 99 if(dfn[fu]<dfn[fv]) swap(fu,fv),swap(u,v); 100 update(rt,1,n,dfn[fu],dfn[u],1); 101 u=fa[fu][0];fu=top[u]; 102 } 103 if(dep[u]<dep[v]) swap(u,v); 104 update(rt,1,n,dfn[v],dfn[u],1); 105 } 106 void init(){ 107 scanf("%d%d",&n,&m); 108 for(int i=1;i<n;i++){ 109 scanf("%d%d",&x,&y); 110 add(x,y); 111 add(y,x); 112 } 113 for(int i=1;i<=m;i++) scanf("%d",&a[i]); 114 dfs1(1,0,0); 115 dfs2(1,0,1); 116 117 118 build(rt,1,n); 119 a[0]=1; 120 for(int i=1;i<=m;i++){//将a[i]加进去 121 upd(a[i],a[i-1]); 122 printf("%d ",2*(num[1]-1)-dep[a[i]]); 123 } 124 } 125 int main(){ 126 init(); 127 128 return 0; 129 }
T3:
留坑放代码...
1 #include<bits/stdc++.h> 2 #define maxn 100005 3 using namespace std; 4 typedef long long ll; 5 int n,a[maxn*2],b[maxn*2];//b:替用数组 6 bool vis[65];//分解t之后哪些位上有 7 ll t,w[65]; 8 char s[maxn]; 9 void ready(){ 10 w[0]=1; 11 for(int i=1;i<=60;i++) w[i]=w[i-1]*2ll; 12 } 13 void fj(ll t){ 14 for(int i=0;i<=60;i++){ 15 if((1ll<<i)&t) vis[i]=1; 16 } 17 } 18 void init(){ 19 scanf("%lld%d",&t,&n); 20 scanf("%s",s); 21 for(int i=1;i<=n;i++) a[i]=a[n*2+2-i]=(s[i-1]=='0'?0:1); 22 fj(t); 23 24 int len=n*2+2; 25 for(int i=0;i<=60;i++){ 26 if(vis[i]){ 27 int dis=w[i]%len; 28 memset(b,0,sizeof(b));//b要清0 29 for(int j=0;j<len;j++){//全部更新 30 if(a[j]==1){ 31 b[(j+dis)%len]^=1;//相当于a[j] 32 b[(j-dis+len)%len]^=1;//一种替换,j=b[(j+dis)%len]^b[(j-dis+len)%len],那每个被亦或一遍 33 } 34 } 35 memcpy(a,b,sizeof(b)); 36 } 37 } 38 for(int i=1;i<=n;i++) printf("%d",a[i]); 39 } 40 int main(){ 41 ready(); 42 init(); 43 44 return 0; 45 }