• 17-06-28模拟赛


    T1:考虑求出所有的环。若该环中点的个数为n,则拆环的方法为为C(1,n)+C(2,n)+...+C(n-1,n)=2n-2种。(全翻转及全不翻转都是环)。

    再求出非环节点的个数m,则方法有2m种。(可以发现每个连通块中中必有环,所以可以都不翻转)根据乘法原理,将所有环的方案数及非环节点的方案数相乘即可。

    注意要用到快速幂。

    Note:注意到每个连通块中有且仅有一个环,进行一次dfs即可。

    Code:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define mod 1000000007
     5 #define MN 200005
     6 #define ll long long
     7 using namespace std;
     8 inline int in(){
     9     int x=0;bool f=0; char c;
    10     for (;(c=getchar())<'0'||c>'9';f=c=='-');
    11     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
    12     return f?-x:x;
    13 }
    14 struct edge{
    15     int to,next;
    16 }e[MN+5],r[MN+5];
    17 int head[MN],rhed[MN],num[MN],ct[MN];
    18 int cnt=0,rct=0,tmp,n,a,pos,sum;
    19 ll res=1ll,rn;
    20 bool vis[MN];
    21 inline void ins(int x,int y){
    22     ++cnt;e[cnt].to=y;e[cnt].next=head[x];head[x]=cnt;
    23     ++rct;r[rct].to=x;r[rct].next=rhed[y];rhed[y]=rct;
    24 }
    25 inline ll qpow(int x){
    26     ll ans=1ll,mul=2ll;
    27     while (x){
    28         if (x&1) ans=(ans*mul)%mod;
    29         mul=(mul*mul)%mod;x>>=1;
    30     }return ans;
    31 }
    32 void dfs(int x){
    33     vis[x]=1;
    34     for (int i=head[x];i;i=e[i].next){
    35         int v=e[i].to;
    36         if (!vis[v]) dfs(v);
    37     }num[++tmp]=x;
    38 }
    39 void rdfs(int x,int k){
    40     vis[x]=1;++ct[k];
    41     for (int i=rhed[x];i;i=r[i].next){
    42         int v=r[i].to;
    43         if (!vis[v]) rdfs(v,k);
    44     }
    45 }
    46 int main()
    47 {
    48     n=in();for (int i=1;i<=n;++i) a=in(),ins(i,a);memset(vis,0,sizeof(vis));
    49     for (int i=1;i<=n;++i) if (!vis[i]) dfs(i);memset(vis,0,sizeof(vis));
    50     for (int i=n;i;--i) if (!vis[num[i]]) rdfs(num[i],++pos);
    51     for (int i=1;i<=pos;++i){
    52         if (ct[i]<=1) continue;
    53         sum+=ct[i];rn=1ll*(qpow(ct[i])-2+mod)%mod;
    54         res=1ll*(res*rn)%mod;
    55     }if (!sum) printf("%lld
    ",1ll*(qpow(n)-1+mod)%mod);
    56     else {
    57         rn=1ll*qpow(n-sum)%mod;res=1ll*(res*rn)%mod;
    58         printf("%lld
    ",res);
    59     }return 0;
    60 }

     T2:经过推理可知,若经过操作能够使负数的个数为奇数,则应尽可能使乘积的绝对值大,即每次将绝对值最小的数的绝对值+x.

    否则使乘积的最小值尽可能小,即每次将绝对值最小的数的绝对值-x.

    若开始时负数的个数为奇数,则每次将绝对值最小的数的绝对值+x.

    否则考虑能否使负数的个数为奇数,若能,则通过操作将绝对值最小的数变号,再每次将绝对值最小的数的绝对值+x.

    若不能,则每次将绝对值最小的数的绝对值-x.

    注意对0的特殊处理。绝对值最小的数用堆维护。

    Code:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 #include<iostream>
     5 #include<algorithm>
     6 #define inf 0x7fffffff
     7 using namespace std;
     8 typedef pair <int,int> P;
     9 inline int in(){
    10     int x=0;bool f=0; char c;
    11     for (;(c=getchar())<'0'||c>'9';f=c=='-');
    12     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
    13     return f?-x:x;
    14 }
    15 inline int abs(int x){return x>0?x:-x;}
    16 int a[200005],nega,posi,n,k,x,pmn,nmx,npos,ppos;
    17 priority_queue<P,vector<P>,greater<P> >q;
    18 int main()
    19 {
    20     n=in();k=in();x=in();pmn=inf;nmx=-inf;
    21     for (int i=1;i<=n;++i){
    22         a[i]=in();q.push(make_pair(abs(a[i]),i));
    23         if (a[i]<0) {++nega;if (a[i]>nmx) nmx=a[i],npos=i;}
    24         if (a[i]>0) {++posi;if (a[i]<pmn) pmn=a[i],ppos=i;}
    25         if (!a[i]&&nmx&&pmn) nmx=pmn=0,npos=ppos=i;
    26     }
    27     if (nega&1){
    28         for (int i=1;i<=k;++i){
    29             int t=q.top().first,tpos=q.top().second;q.pop();
    30             if (a[tpos]>=0) a[tpos]+=x;else a[tpos]-=x;
    31             q.push(make_pair(t+x,tpos));
    32         }
    33     }else{
    34         int d,dpos;
    35         if (abs(nmx)<pmn) d=abs(nmx),dpos=npos;else d=abs(pmn),dpos=ppos;
    36         if (1ll*d<1ll*x*k){
    37             k-=(d/x+1);q.pop();
    38             if (a[dpos]>=0) a[dpos]-=(d/x+1)*x;
    39             else a[dpos]+=(d/x+1)*x;
    40             q.push(make_pair(abs(a[dpos]),dpos));
    41             for (int i=1;i<=k;++i){
    42                 int t=q.top().first,tpos=q.top().second;q.pop();
    43                 if (a[tpos]>=0) a[tpos]+=x;else a[tpos]-=x;
    44                 q.push(make_pair(t+x,tpos));
    45             }
    46         }else {
    47             for (int i=1;i<=k;++i){
    48                 int t=q.top().first,tpos=q.top().second;q.pop();
    49                 if (a[tpos]>=0) a[tpos]-=x;else a[tpos]+=x;
    50                 q.push(make_pair(t-x,tpos));
    51             }
    52         }
    53     }for (int i=1;i<=n;++i) printf("%d ",a[i]);return 0;
    54 }

    T3:

    注意到将路变为墙时不会将一个区域分割,也不会将一个只有一格的区域填满,可以发现每块区域都不会被分割或消失,考虑用带权并查集维护一块区域可到达点的个数。

    对于初始状态,dfs求出连通块及其点数。

    对于查询操作,找到所有点所属连通块的父连通块的点数最大值即可。

    对于修墙操作,将该节点所属连通块的父连通块点数减一,并将该节点所属连通块数修改为0.

    对于修路操作,将该路设为新连通块,若与该路相连节点为路,则合并该路所属父连通块与该路相连节点所属父连通块。

    注意合并时将其中一连通块的权值设为0。

    Code:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define MN 1000005
     5 using namespace std;
     6 inline int in(){
     7     int x=0;bool f=0; char c;
     8     for (;(c=getchar())<'0'||c>'9';f=c=='-');
     9     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
    10     return f?-x:x;
    11 }
    12 char mp[MN];
    13 int fa[MN<<1],siz[MN<<1],num[MN];
    14 int n,m,x,y,q,cnt=0,tp,w;
    15 inline int gf(int x){return fa[x]?fa[x]=gf(fa[x]):x;}
    16 inline void dfs(int x,int y,int ct){
    17     if (mp[x*m+y]!='.'||num[x*m+y]) return;
    18     num[x*m+y]=ct;++siz[num[x*m+y]];
    19     if (x) dfs(x-1,y,ct);if (y) dfs(x,y-1,ct);
    20     if (x+1<n) dfs(x+1,y,ct);if (y+1<m) dfs(x,y+1,ct);
    21 }
    22 inline void uni(int x,int y,int p,int q){
    23     int f1=gf(num[x*m+y]),f2=gf(num[p*m+q]);
    24     if (mp[p*m+q]!='.'||f1==f2) return;
    25     siz[f2]+=siz[f1];siz[f1]=0;fa[f1]=f2;
    26 }
    27 
    28 int main()
    29 {
    30     n=in();m=in();memset(fa,0,sizeof(fa));
    31     for (int i=0;i<n;++i) scanf("%s",mp+i*m);
    32     for (int i=0;i<n;++i)
    33     for (int j=0;j<m;++j)
    34     if (mp[i*m+j]=='.'&&!num[i*m+j]) dfs(i,j,++cnt);q=in();
    35     for (int i=1;i<=q;++i){
    36         tp=in();w=in();
    37         if (tp==1){
    38             int mx=0,pos=1;
    39             for (int j=1;j<=w;++j){
    40                 x=in()-1;y=in()-1;
    41                 if (mp[x*m+y]=='.'&&siz[gf(num[x*m+y])]>mx) mx=siz[gf(num[x*m+y])],pos=j;
    42             }printf("%d
    ",pos);
    43         }else for (int j=1;j<=w;++j){
    44             x=in()-1;y=in()-1;
    45             if (mp[x*m+y]=='.'){
    46                 --siz[gf(num[x*m+y])];
    47                 mp[x*m+y]='*';num[x*m+y]=0;
    48             }else{
    49                 num[x*m+y]=++cnt;++siz[num[x*m+y]];mp[x*m+y]='.';
    50                 if (x) uni(x,y,x-1,y);if (y) uni(x,y,x,y-1);
    51                 if (x+1<n) uni(x,y,x+1,y);if (y+1<m) uni(x,y,x,y+1);
    52             }
    53         }
    54     }return 0;
    55 }
  • 相关阅读:
    第一阶段用户模板和用户场景
    团队开发冲刺第十二天
    第十周总结
    团队开发冲刺第十一天
    团队开发冲刺第十天(实现页面展示评论数与点赞数)
    团队开发冲刺第九天(实现收藏,点赞,关注功能)
    团队开发冲刺第八天(实现评论功能)
    软件用户场景分析
    第九周总结
    团队开发冲刺第六天(新闻详情页的展示)
  • 原文地址:https://www.cnblogs.com/codingutopia/p/test170628.html
Copyright © 2020-2023  润新知