zoukankan      html  css  js  c++  java
  • noip模拟测试19


    T1:Count

      首先容易发现块的大小一定是n的约数,枚举约数$O(sqrt n)$

      考虑怎么判定

      设块大小为k

      发现只要最下方的子树$(a)$大小是$k$,包含a的子树$(b)$大小是$2k$,包含b的子树$(c)$大小是$3k$……

      即:只需要有$n/k$个子树的大小是$k$的倍数即可

      所以就可以$O(n)$的判定了,然后就无脑提交$O(n sqrt n )$过百万???

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<queue>
    #include<cstdlib>
    #include<vector>
    using namespace std;
    const int MAXN=1000005;
    int n,ans,siz[MAXN];
    struct node {
        int to,nxt;
    }mp[MAXN*2];
    int h[MAXN],tot;
    void dfs(int u,int fa) {
        siz[u]=1;
        for(int i=h[u];i;i=mp[i].nxt) {
            int v=mp[i].to;
            if(v==fa) continue;
            dfs(v,u);
            siz[u]+=siz[v];
        }
    }
    inline int R() {
        int a=0;char c=getchar();
        while(c>'9'||c<'0')c=getchar();
        while(c>='0'&&c<='9')a=a*10+c-'0',c=getchar();
        return a;
    }
    int main() {
        n=R();
        for(int i=1,aa,bb;i<n;++i) {
            aa=R();bb=R();
            mp[++tot].nxt=h[aa];
            mp[tot].to=bb;h[aa]=tot;
            mp[++tot].nxt=h[bb];
            mp[tot].to=aa;h[bb]=tot;
        }
        dfs(1,0);
        for(int i=2;i<n;++i) if(n%i==0) {
            int cnt=0;
            for(int j=1;j<=n;j++)
                if(siz[j]%i==0) ++cnt;
            if(n/i==cnt) ++ans;
        }
        printf("%d
    ",ans+2);
        return 0;
    }
    t1 Code


    T2:Dinner

      没想到倍增,想到了二分可以跳到的点,但m的范围没有给,若m与n同级复杂度就爆了,所以没写

      结果发现m实际上很小,好多人都用二分水过了……

      

      首先断环成链,二分答案

      最暴力的判定是枚举端点,再一步一步贪心的跳,复杂度$O(n^2logn)$

      考虑优化跳的复杂度

      对于每次check,可以$O(nlogn)$的预处理跳$2^n$步可以跳到哪里

      然后把m二进制拆开跳,复杂度$O((nlogn+logm)*logn)$,若m与n同级$O(nlog^2n)$

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<iostream>
     6 #include<queue>
     7 #include<cstdlib>
     8 #include<vector>
     9 using namespace std;
    10 const int MAXN=50005;
    11 int n,m,ans,suma,mx,t[MAXN*2],nxt[MAXN*2][20];
    12 inline int R() {
    13     int a=0;char c=getchar();
    14     while(c>'9'||c<'0')c=getchar();
    15     while(c>='0'&&c<='9')a=a*10+c-'0',c=getchar();
    16     return a;
    17 }
    18 bool check(int lim) {
    19     for(int i=1;i<=n;i++) {
    20         int pos=i,tm=m;
    21         for(int j=18;j>=0;j--) {
    22             if((1<<j)>tm) continue;
    23             pos=nxt[pos][j];
    24             tm-=(1<<j);
    25         }
    26         if(pos-i>=n) return 1;
    27     }
    28     return 0;
    29 }
    30 void first(int lim) {
    31     int l=1,sum=0;
    32     for(int i=1;i<=2*n;i++)
    33         if(sum+t[i]<=lim) sum+=t[i];
    34         else {
    35             while(l<i&&sum+t[i]>lim) {
    36                 nxt[l][0]=i;
    37                 sum-=t[l];
    38                 ++l;
    39             }
    40             sum+=t[i];
    41         }
    42     while(l<=2*n) nxt[l][0]=2*n+1,++l;
    43     for(int i=0;i<=18;i++) nxt[2*n+1][i]=2*n+1;
    44     for(int i=1;i<=18;i++)
    45         for(int j=1;j+(1<<(i-1))<=2*n;j++)
    46             nxt[j][i]=nxt[nxt[j][i-1]][i-1];
    47 }
    48 int main() {
    49     scanf("%d%d",&n,&m);
    50     for(int i=1;i<=n;++i) scanf("%d",&t[i]);
    51     for(int i=1;i<=n;++i)
    52         t[i+n]=t[i],suma+=t[i],mx=max(mx,t[i]);
    53     int l=mx,r=suma;
    54     while(l<=r) {
    55         int mid=(l+r)>>1;
    56         first(mid);
    57         if(check(mid))
    58             ans=mid,r=mid-1;
    59         else l=mid+1;
    60     }
    61     printf("%d
    ",ans);
    62     return 0;
    63 }
    t2 Code


    T3:Chess

      首先第一问很简单,可以直接双端队列bfs或建图跑最短路

      然后看第二问,发现只有走的空地不同才算不同的方案

      发现n的范围很小,于是对于dfs每一个敌军的连通块,看它连接着哪些空地,在这些空地间两两连边

      再将直接可以到达的两空地间连边

      特别的:可以将敌人的帅看做一个空地进行连边

      跑最短路计数就行了

      注意:相同的边只能连一次,所以可以用邻接矩阵来存边

      (有点毒瘤……)

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<cstdlib>
      5 #include<cmath>
      6 #include<iostream>
      7 #include<queue>
      8 #include<vector>
      9 #define ll long long
     10 using namespace std;
     11 const int MAXN=70,INF=0x3f3f3f3f;
     12 int n,m,bx,by,ex,ey,eid,s[MAXN][MAXN];
     13 int dx[8]={-1,-2,-2,-1,1,2,2,1},dy[8]={-2,-1,1,2,2,1,-1,-2};
     14 struct node {
     15     int to,nxt,dis;
     16 }mp[MAXN*MAXN*8];
     17 int h[MAXN*MAXN],tot;
     18 int id(int x,int y) {
     19     return (x-1)*m+y;
     20 }
     21 void add(int x,int y,int z) {
     22     mp[++tot].dis=z;
     23     mp[tot].to=y;
     24     mp[tot].nxt=h[x];
     25     h[x]=tot;
     26 }
     27 void build() {
     28     for(int i=1;i<=n;i++) {
     29         for(int j=1;j<=m;j++) {
     30             if(s[i][j]==2) continue;
     31             if(s[i][j]==4) {ex=i,ey=j;continue;}
     32             if(s[i][j]==3) bx=i,by=j;
     33             for(int k=0;k<8;k++) {
     34                 int nx=i+dx[k],ny=j+dy[k];
     35                 if(nx<1||ny<1||nx>n||ny>m) continue;
     36                 if(s[nx][ny]==2) continue;
     37                 add(id(i,j),id(nx,ny),s[nx][ny]!=1&&s[nx][ny]!=4);
     38             }
     39         }
     40     }
     41 }
     42 int ver[MAXN*MAXN][MAXN*MAXN],dis[MAXN*MAXN];
     43 vector<int> tver;
     44 bool vis[MAXN*MAXN],flag;
     45 void dfs(int u) {
     46     for(int i=h[u];i;i=mp[i].nxt) {
     47         int v=mp[i].to;
     48         if(vis[v]) continue;
     49         vis[v]=1;
     50         if(v==eid) flag=1;
     51         if(!mp[i].dis) dfs(v);
     52         else if(mp[i].dis==1) tver.push_back(v);
     53     }
     54 }
     55 void new_build() {
     56     eid=id(ex,ey);
     57     memset(vis,0,sizeof(vis));
     58     for(int i=1;i<=n;i++) {
     59         for(int j=1;j<=m;j++) if(s[i][j]==1){
     60             tver.clear();flag=0;
     61             vis[id(i,j)]=1;dfs(id(i,j));
     62             for(int k=0;k<tver.size();++k)
     63                 for(int l=0;l<tver.size();++l)
     64                     ver[tver[k]][tver[l]]=ver[tver[l]][tver[k]]=1;
     65             if(flag) for(int k=0;k<tver.size();++k)
     66                         ver[tver[k]][eid]=1;
     67             memset(vis,0,sizeof(vis));
     68         }
     69     }
     70     for(int i=1;i<=n;i++)
     71         for(int j=1;j<=m;j++) if(s[i][j]==0||s[i][j]==3)
     72             for(int k=h[id(i,j)];k;k=mp[k].nxt)
     73                 if(mp[k].dis||mp[k].to==eid)
     74                     ver[id(i,j)][mp[k].to]=ver[mp[k].to][id(i,j)]=1;
     75 }
     76 ll cnt[MAXN*MAXN];
     77 void get_cnt() {
     78     memset(dis,0x3f,sizeof(dis));
     79     dis[id(bx,by)]=0;cnt[id(bx,by)]=1;
     80     priority_queue<pair<int,int> > q;
     81     q.push(make_pair(0,id(bx,by)));
     82     while(!q.empty()) {
     83         int u=q.top().second; q.pop();
     84         if(vis[u]) continue;
     85         vis[u]=1;
     86         for(int i=1;i<=n*m;i++) if(i!=u){
     87             int v=i,ds=ver[u][i];
     88             if(!ds) continue;
     89             if(dis[v]>dis[u]+ds) {
     90                 dis[v]=dis[u]+ds;
     91                 cnt[v]=cnt[u];
     92                 q.push(make_pair(-dis[v],v));
     93             } else if(dis[v]==dis[u]+ds) cnt[v]+=cnt[u];
     94         }
     95     }
     96     printf("%lld
    ",cnt[eid]);
     97 }
     98 void dijkstra() {
     99     priority_queue<pair<int,int> > q;
    100     q.push(make_pair(0,id(bx,by)));
    101     memset(dis,0x3f,sizeof(dis));
    102     dis[id(bx,by)]=0;
    103     while(!q.empty()) {
    104         int u=q.top().second; q.pop();
    105         if(vis[u]) continue;
    106         vis[u]=1;
    107         for(int i=h[u];i;i=mp[i].nxt) {
    108             int v=mp[i].to,ds=mp[i].dis;
    109             if(dis[v]>dis[u]+ds) {
    110                 dis[v]=dis[u]+ds;
    111                 q.push(make_pair(-dis[v],v));
    112             }
    113         }
    114     }
    115     if(dis[id(ex,ey)]==INF) {
    116         printf("-1
    ");exit(0);
    117     } else printf("%d
    ",dis[id(ex,ey)]);
    118 }
    119 int main() {
    120     scanf("%d%d",&n,&m);
    121     for(int i=1;i<=n;i++)
    122         for(int j=1;j<=m;j++)
    123             scanf("%d",&s[i][j]);
    124     build();
    125     dijkstra();
    126     new_build();
    127     get_cnt();
    128     return 0;
    129 }
    t3 Code

  • 相关阅读:
    任务---内部揭秘
    线程
    c#制作com组件供wincc调用
    线程----计算限制的异步操作2
    随笔,聊一聊任务取消
    C#制作Wincc组件进行配方管理(二)
    MongoDB导入导出以及数据库备份111
    浏览器访问页面步骤
    C#中的继承和多态
    网关和路由器的区别
  • 原文地址:https://www.cnblogs.com/Gkeng/p/11354365.html
Copyright © 2011-2022 走看看