正睿 2018 提高组十连测 Day5

前言:敦爷的题真的好良心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\n",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 }

 

posted @ 2018-09-24 21:55  degage  阅读(356)  评论(0编辑  收藏  举报