zoukankan      html  css  js  c++  java
  • 2018.08.16

    遗憾啊,三道题都不难,但是一道也没AC。

    T1 mine

    可以看出是个DP题(然而我考场上写的并不是DP,而且它对拍没错),

    设:

    f[i][j][0/1]代表已经处理完前i个数,且第i个数取j的方案数(0/1代表j==1时地雷在左/右,其他情况无用)

    (j:3为是炸弹,0,1,2对应题目中的0,1,2)

    于是便有:

    f[i][0][0]=f[i-1][0][0]+f[i-1][1][0];(a[i]=='0'/'?')

    f[i][1][0]=f[i-1][3][0];(a[i]=='1'/'?')

    f[i][1][1]=f[i-1][0][0]+f[i-1][1][0];(a[i]=='1'/'?')

    f[i][2][0]=f[i-1][3][0];(a[i]=='2'/'?')

    f[i][3][0]=f[i-1][3][0]+f[i-1][1][1]+f[i-1][2][0];(a[i]=='3'/'?')(注意这里可以由上次的3转移)

    设初值需要分类讨论,不再赘述。

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 #define AA puts("ALITA")
     4 #define DD puts("DYBALA")
     5 using namespace std;
     6 const int N=1e6+10,mod=1e9+7;
     7 int ans,n,f[N][4][2];
     8 char s[N];
     9 signed main()
    10 {
    11         //freopen("1.in","r",stdin);
    12         //freopen("1.out","w",stdout);
    13         scanf("%s",s+1);
    14         n=strlen(s+1);
    15         if(s[1]=='0'||s[1]=='?') f[1][0][0]=1;
    16         if(s[1]=='1'||s[1]=='?') f[1][1][1]=1;
    17         if(s[1]=='*'||s[1]=='?') f[1][3][0]=1;
    18         for(int i=2;i<=n;i++)
    19         {
    20                 if(s[i]=='0'||s[i]=='?') f[i][0][0]=(f[i-1][1][0]+f[i-1][0][0])%mod;
    21                 if(s[i]=='1'||s[i]=='?')
    22                 {
    23                         f[i][1][0]=f[i-1][3][0];
    24                         f[i][1][1]=(f[i-1][0][0]+f[i-1][1][0])%mod;
    25                 }
    26                 if(s[i]=='2'||s[i]=='?') f[i][2][0]=f[i-1][3][0];
    27                 if(s[i]=='*'||s[i]=='?') f[i][3][0]=(f[i-1][1][1]+f[i-1][2][0]+f[i-1][3][0])%mod;
    28         }
    29         if(s[n]=='0'||s[n]=='?') (ans+=f[n][0][0])%=mod;
    30         if(s[n]=='1'||s[n]=='?') (ans+=f[n][1][0])%=mod;
    31         if(s[n]=='*'||s[n]=='?') (ans+=f[n][3][0])%=mod;
    32         printf("%lld",ans);
    33         return 0;
    34 }
    T1

    T2 water

    0~?分:

    对于每个点枚举能到达的高度,bfs检查是否合法,时间复杂度$ O(n^2m^2*1e9) $

    60分做法:

    把枚举变为二分,复杂度大大降低,$ O(n^2m^2log2(1e9)) $,性价比较高

    100分做法:

    我们观察水流出的过程,可以看出一个块的ans一定为它走到矩阵外路径的最大值的最小值,

    因为要想出去,一定是路径上最大值,而它可以从四面八方出去,所以在所以的路径的最大值中取min。

    之后考虑如何建图,两个块之间的路的权值就是两个块的高度的最大值,源点的高度就是0。

    1>求单源最短路,DJ即可(网格图Spfa可能会死)

    2>最小生成树,f[i]即为i到源点(根)的路径的权值最大值。

      1 #include<bits/stdc++.h>
      2 #define int long long
      3 #define max(a,b) (a>b?a:b)
      4 #define AA puts("ALITA")
      5 #define DD puts("DYBALA")
      6 using namespace std;
      7 const int N=305;
      8 int sum,tot,cnt,T,n,m,a[N][N],ma[N][N],fa[N*N],head[N*N],to[N*N*2],ne[N*N*2],w[N*N*2],dis[N*N];
      9 int A[2]={0,-1};
     10 int B[2]={-1,0};
     11 struct edge{int fr,to,w;}e[N*N*4];
     12 int read()
     13 {
     14         register int sum,k=1;register char s;
     15         while(s=getchar(),s<'0'||s>'9') if(s=='-') k=-1;sum=s-'0';
     16         while(s=getchar(),s>='0'&&s<='9') sum=sum*10+s-'0';
     17         return k*sum;
     18 }
     19 void add(int x,int y,int z)
     20 {
     21         e[++cnt].fr=x;
     22         e[cnt].to=y;
     23         e[cnt].w=z;
     24 }
     25 void connect(int x,int y,int z)
     26 {
     27         to[++sum]=y;
     28         w[sum]=z;
     29         ne[sum]=head[x];
     30         head[x]=sum;
     31 }
     32 bool comp(edge l,edge r)
     33 {
     34         return l.w<r.w;
     35 }
     36 int get(int x)
     37 {
     38         if(fa[x]==x) return x;
     39         return fa[x]=get(fa[x]);
     40 }
     41 void dfs(int x,int father)
     42 {
     43         for(int i=head[x];i;i=ne[i])
     44         {
     45                 int y=to[i];
     46                 if(y==father) continue;
     47                 dis[y]=max(dis[x],w[i]);
     48                 dfs(y,x);
     49         }
     50 }
     51 signed main()
     52 {
     53         //freopen("1.in","r",stdin);
     54         n=read();m=read();
     55         T=n*m+1;
     56         for(int i=1;i<=n;i++)
     57         {
     58                 for(int j=1;j<=m;j++)
     59                 {
     60                         ma[i][j]=++tot;
     61                         a[i][j]=read();
     62                 }
     63         }
     64         for(int i=1;i<=n;i++)
     65         {
     66                 for(int j=1;j<=m;j++)
     67                 {
     68                         for(int k=0;k<2;k++)
     69                         {
     70                                 int l=i+A[k],r=j+B[k];
     71                                 if(!ma[l][r]) continue;
     72                                 add(ma[i][j],ma[l][r],max(a[i][j],a[l][r]));
     73                         }
     74                 }
     75         }
     76         for(int i=1;i<=n;i++)
     77         {
     78                 add(ma[i][1],T,max(a[i][1],0));
     79                 add(ma[i][m],T,max(a[i][m],0));
     80         }
     81         for(int i=2;i<m;i++)
     82         {
     83                 add(ma[1][i],T,max(a[1][i],0));
     84                 add(ma[n][i],T,max(a[n][i],0));
     85         }
     86         for(int i=1;i<=tot+1;i++) fa[i]=i;
     87         sort(e+1,e+cnt+1,comp);
     88         for(int i=1,x,y;i<=cnt;i++)
     89         {
     90                 x=get(e[i].fr),y=get(e[i].to);
     91                 if(x==y) continue;
     92                 fa[x]=y;
     93                 connect(e[i].fr,e[i].to,e[i].w);
     94                 connect(e[i].to,e[i].fr,e[i].w);
     95         }
     96         dfs(T,0);
     97         for(int i=1;i<=n;i++)
     98         {
     99                 for(int j=1;j<=m;j++)
    100                 {
    101                         printf("%lld ",dis[ma[i][j]]-a[i][j]);
    102                 }
    103                 puts("");
    104         }
    105         return 0;
    106 }
    T2

    T3 gcd

    考场上想到了正解,但当时一时脑抽觉得一个500000的数的质因子可能有好多好多个...(大雾)

    20分做法:

    暴力搞它~,时间复杂度$ O(nm*2log2(max(a,b)) $

    50分做法:

    30分部分分满足max(a[i])<=100,于是可以用一个桶来存储,更新答案,复杂度$ O(m*100)

    (注意gcd要预处理,否则像我这样自带大常数的根本过不去!!!)

    100分做法:

    跟题解不太一样,但又有异曲同工之妙。

    设sum1为原来被激活的数的个数,sum2为其中与a[i]组成不合法的数的个数

    显然nowans=lastans+sum1-sum2;sum1好求,关键在于sum2。

    仍然是用桶v[x]代表x|a[i]的个数,我们可以容斥来解决,

    具体来说就是:枚举每个素因子是否取,在$ O(2^6) $内求出每种情况,容斥即可。

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 #define max(a,b) (a>b?a:b)
     4 #define AA puts("ALITA")
     5 #define DD puts("DYBALA")
     6 using namespace std;
     7 const int N=2e5+10;
     8 int sum,ans,n,m,tot[N],mark[N],a[N],p[N][8],v[N*3];
     9 int read()
    10 {
    11         register int sum,k=1;register char s;
    12         while(s=getchar(),s<'0'||s>'9') if(s=='-') k=-1;sum=s-'0';
    13         while(s=getchar(),s>='0'&&s<='9') sum=sum*10+s-'0';
    14         return k*sum;
    15 }
    16 void init(int x,int y)
    17 {
    18         for(int i=2;i<=sqrt(x);i++)
    19         {
    20                 if(x%i) continue;
    21                 p[y][++tot[y]]=i;
    22                 while(x%i==0) x/=i;
    23         }
    24         if(x!=1) p[y][++tot[y]]=x;
    25 }
    26 void dfs(int x,int y,int z,int val)
    27 {
    28         if(y==tot[x]+1)
    29         {
    30                 if(val==1) return;
    31                 ans+=v[val]*z;
    32                 return;
    33         }
    34         dfs(x,y+1,z*(-1),val*p[x][y]);
    35         dfs(x,y+1,z,val);
    36 }
    37 void redfs(int x,int y,int z,int val)
    38 {
    39         if(y==tot[x]+1) 
    40         {
    41                 v[val]+=z;
    42                 return;
    43         }
    44         redfs(x,y+1,z,val*p[x][y]);
    45         redfs(x,y+1,z,val);
    46 }
    47 signed main()
    48 {
    49         //freopen("1.in","r",stdin);
    50         n=read();m=read();
    51         for(int i=1;i<=n;i++) 
    52         {
    53                 a[i]=read();
    54                 init(a[i],i);
    55         }
    56         for(int i=1,x;i<=m;i++)
    57         {
    58                 x=read();
    59                 mark[x]^=1;
    60                 if(mark[x])
    61                 {
    62                         ans+=sum;
    63                         sum++;
    64                         dfs(x,1,1,1);
    65                         redfs(x,1,1,1);
    66                 }
    67                 else 
    68                 {
    69                         sum--;
    70                         ans-=sum;
    71                         redfs(x,1,-1,1);
    72                         dfs(x,1,-1,1);
    73                 }
    74                 printf("%lld
    ",ans);
    75         }
    76         return 0;
    77 }
    T3
  • 相关阅读:
    pcDuino无显示器刷机与使用
    pcDuino安装vnc进行远程控制
    pcDuino 刷系统-卡刷
    HDU 5441 2015长春站online1005(并查集)
    HYSBZ 2002 Bounce 弹飞绵羊(分块)
    HYSBZ 2243 染色 LCT学习
    HYSBZ 2049 Cave 洞穴勘测
    SPOJ 375 LCT学习
    HDU 4010 动态树LCT学习
    ZJOI2008 树的统计 树链剖分学习
  • 原文地址:https://www.cnblogs.com/AthosD/p/11365289.html
Copyright © 2011-2022 走看看