zoukankan      html  css  js  c++  java
  • JZOJ 3960 鸡腿の出行

    SOL: 

      我们可以用tarjan求割点和边双,然后便成了一颗树,问题转成了 树上两点距离。

    #include<bits/stdc++.h>
    #define ull unsigned long long 
    #define LL long long
    #define mo 998244353
    #define B 80
    using namespace std;
    //const int _P=1000007;
    //const int _N=1000005;
    //struct HashMap{
    //  int head[_P],inum,clk;
    //  int tag[_P];
    //  ull h[_N]; int c[_N],g[_N],next[_N];
    //  void _new(){
    //    ++clk; inum=0;
    //  }
    //  int Head(int x){
    //    return tag[x]!=clk?(tag[x]=clk,head[x]=0):head[x];
    //  }
    //  int &get(ull _h,int _c){
    //    int hs=(_h*233+_c)%_P;
    //    for (int p=Head(hs);p;p=next[p])
    //      if (h[p]==_h && c[p]==_c)
    //    return g[p];
    //    h[++inum]=_h; c[inum]=_c; g[inum]=0; next[inum]=head[hs]; head[hs]=inum;
    //    return g[inum];
    //  }
    //}f[2];
    struct Ha{
        #define HaN 1000007
        #define HaM 1000007
        int head[HaN],net[HaM],fall[HaM],tag[HaN],tot,tim,
        c[HaM],g[HaM];
        ull h[HaM];
        void _new() {++tim; tot=0;}
        int push(int x) {
            return (tag[x]^tim)?(tag[x]=tim,head[x]=0):head[x];
        }
        int &get(ull _h,int _c) {
            static int hs;
            hs=(_h*233+_c)%HaN;
            for (int i=push(hs);i;i=net[i]) 
             if (h[i]==_h&&c[i]==_c) return g[i];
            h[++tot]=_h,c[tot]=_c; g[tot]=0; net[tot]=head[hs]; head[hs]=tot;
            return g[tot];
        }
    }f[2];
    int n,m,g,p,c,nc; char ha[107],pa[107];
    LL K,ff[107][107],sum[107*107],l,r,ans;
    ull se[107],h,tt,nh;
    signed main () {
    //    freopen("c.in","r",stdin);
        scanf("%d%d%lld",&n,&m,&K);
        scanf("%s",ha+1); scanf("%s",pa+1);
        ff[1][1]=K;
        for (int i=1;i<=n;i++)
         for (int j=1;j<=m;j++)
          ff[i+1][j]+=ff[i][j]>>1,ff[i][j+1]+=ff[i][j]>>1,ff[i][j]&=1;
        for (int i=1;i<=n;i++) ans+=(ha[i]=='1')*ff[i][m+1],ff[i][m+1]=0;
        for (int i=1;i<=m;i++) ans+=(pa[i]=='1')*ff[n+1][i],ff[n+1][i]=0;
        se[0]=1; for (int i=1;i<=m;i++) se[i]=se[i-1]*B;
        int t=0; f[t]._new();
        ull tmp=0; for (int i=m;i;i--) tmp=tmp*B+ff[1][i];
        f[t].get(tmp,0)=1;
        for (int i=1;i<=n*m;i++,t^=1){
        int x=(i-1)/m+1,y=(i-1)%m+1;
        f[t^1]._new();
        for (int p=1;p<=f[t].tot;p++){
          h=f[t].h[p]; c=f[t].c[p],g=f[t].g[p];
          tt=h%80;
          nh=h/80+se[m-1]*ff[x+1][y]; nc=c;
          if (y<m) nh+=(tt+1)/2;
          else nc+=((tt+1)/2)*(ha[x]=='1');
          if (x<n) nh+=se[m-1]*(tt/2);
          else nc+=(tt/2)*(pa[y]=='1');
    //       cerr<<nh<<' '<<nc<<endl;
          (f[t^1].get(nh,nc)+=g)%=mo;
          nh=h/80+se[m-1]*ff[x+1][y]; nc=c;
          if (y<m) nh+=tt/2;
          else nc+=(tt/2)*(ha[x]=='1');
          if (x<n) nh+=se[m-1]*((tt+1)/2);
          else nc+=((tt+1)/2)*(pa[y]=='1');
    //      cerr<<nh<<' '<<nc<<endl;
          (f[t^1].get(nh,nc)+=g)%=mo;
        }
      }
        for (int q=1;q<=f[t].tot;q++) (sum[f[t].c[q]]+=f[t].g[q])%=mo;
        for (int i=1;i<=n*m;i++) (sum[i]+=sum[i-1])%=mo;
        scanf("%d",&p);
        while (p--) {
          scanf("%lld%lld",&l,&r);
          l=max(l,ans); r=min(r,ans+n*m);
          if (l>r){printf("0
    "); continue;}
          if (l==ans) printf("%d
    ",sum[r-ans]);
          else printf("%d
    ",(sum[r-ans]+mo-sum[l-ans-1])%mo);
        }
        return 0; 
    }
  • 相关阅读:
    call()与apply()的作用与区别
    Tomcat8/9的catalina.out中文乱码问题解决
    怎样查看Jenkins的版本
    每日日报2020.8.18
    528. Random Pick with Weight
    875. Koko Eating Bananas
    721. Accounts Merge
    515. Find Largest Value in Each Tree Row
    286. Walls and Gates (Solution 1)
    408. Valid Word Abbreviation
  • 原文地址:https://www.cnblogs.com/rrsb/p/9299172.html
Copyright © 2011-2022 走看看