• 正睿 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
    ",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 }
  • 相关阅读:
    firefox上网问题解决
    ubuntu内核的编译安装
    ubuntu常用命令
    source insight 添加文件类型
    ubuntu版本查看命令
    百年孤独与拉丁美洲历史--转载
    Guess Number Higher or Lower II--困惑
    Symmetric Tree
    一棵开花的树
    yii2 mysql数据库读写分离配置
  • 原文地址:https://www.cnblogs.com/degage/p/9696892.html
Copyright © 2020-2023  润新知