zoukankan      html  css  js  c++  java
  • [校内训练20_06_01]ABC

    1.给出8个函数f(a,b,c)=k,其中a,b,c,k均为一个bool。对于一个长度为奇数的 零 一 字符串,我们称之为好的,当且仅当存在一种操作方法,使得这个字符串能变为1:

      1.选出一个奇数i。令S=str[1,i],T=str[i+1,n]

      2.从右往左将末尾3个数字替换为f(a,b,c)。直到S长度为1。

      3.str=S+T

    现在字符串中有一些问号,问有多少种将问号替换为0或1的不同的方案,使得这个字符串是好的。

    我们考虑对于一个字符串,如何线性判断是不是好的。显然整个过程可以看成是一个栈的进入和弹出,而一个栈的实际影响相当于函数G[a,b](x),表示若x=0,返回a,否则返回b。

    每次新加入两个数,要么是直接塞入栈中,更新函数。要么是先加入一个数,获得返回值之后加入另一个数,更新函数。

    不同的G只有4个,将这个过程变为dp的状态即可计数。

      1 #define mod 998244353
      2 #include<bits/stdc++.h>
      3 using namespace std;
      4 typedef long long int ll;
      5 const int maxn=1E6+5;
      6 string str;
      7 int n;
      8 int c[2][2][2];
      9 int a[maxn];
     10 int to[4][4],what[2][2],out[4][2];
     11 ll f[maxn][17];
     12 inline void add(ll&x,ll y)
     13 {
     14     x=(x+y)%mod;
     15 }
     16 inline void solve()
     17 {
     18     string x;
     19     cin>>x;
     20     c[0][0][0]=x[0]-'0';
     21     c[1][0][0]=x[1]-'0';
     22     c[0][1][0]=x[2]-'0';
     23     c[1][1][0]=x[3]-'0';
     24     c[0][0][1]=x[4]-'0';
     25     c[1][0][1]=x[5]-'0';
     26     c[0][1][1]=x[6]-'0';
     27     c[1][1][1]=x[7]-'0';
     28     cin>>str;
     29     n=str.size();
     30     str="!"+str;
     31     for(int i=1;i<=n;++i)
     32         a[i]=str[i]-'0';
     33     for(int a1=0;a1<=1;++a1)
     34         for(int b1=0;b1<=1;++b1)
     35             for(int a2=0;a2<=1;++a2)
     36                 for(int b2=0;b2<=1;++b2)
     37                 {
     38                     if(a2==0&&b2==0)
     39                         to[a1+b1*2][a2+b2*2]=a1+a1*2;
     40                     if(a2==0&&b2==1)
     41                         to[a1+b1*2][a2+b2*2]=a1+b1*2;
     42                     if(a2==1&&b2==0)
     43                         to[a1+b1*2][a2+b2*2]=b1+a1*2;
     44                     if(a2==1&&b2==1)
     45                         to[a1+b1*2][a2+b2*2]=b1+b1*2;
     46                     out[a1+b1*2][0]=a1;
     47                     out[a1+b1*2][1]=b1;
     48                 }
     49     for(int i=0;i<=1;++i)
     50         for(int j=0;j<=1;++j)
     51         {
     52             int x=c[i][j][0],y=c[i][j][1];
     53             what[i][j]=x+y*2;
     54         }
     55     memset(f,0,sizeof(f));
     56     f[0][1<<2]=1;
     57     for(int i=0;i<n-1;i+=2)
     58         for(int i1=0;i1<=1;++i1)
     59             for(int i2=0;i2<=1;++i2)
     60             {
     61                 if(a[i+1]!='?'-'0'&&i1!=a[i+1])
     62                     continue;
     63                 if(a[i+2]!='?'-'0'&&i2!=a[i+2])
     64                     continue;
     65                 int num=what[i1][i2];
     66                 for(int S=0;S<(1<<4);++S)
     67                 {
     68                     if(!f[i][S])
     69                         continue;
     70                     int nS=0;
     71                     for(int k=0;k<4;++k)
     72                         if(S&(1<<k))
     73                         {
     74                             nS|=1<<to[k][num];
     75                             nS|=1<<what[out[k][i1]][i2];
     76                         }
     77                     add(f[i+2][nS],f[i][S]);
     78                 }
     79             }
     80     ll ans=0;
     81     for(int i=0;i<=1;++i)
     82     {
     83         if(a[n]!='?'-'0'&&i!=a[n])
     84             continue;
     85         for(int S=0;S<(1<<4);++S)
     86             for(int k=0;k<4;++k)
     87                 if((S&(1<<k))&&out[k][i]==1)
     88                 {
     89                     add(ans,f[n-1][S]);
     90                     break;
     91                 }
     92     }
     93     cout<<ans<<endl;
     94 }
     95 int main()
     96 {
     97     freopen("junior.in","r",stdin);
     98     freopen("junior.out","w",stdout);
     99     ios::sync_with_stdio(false);
    100     int T;
    101     cin>>T;
    102     while(T--)
    103         solve();
    104     return 0;
    105 }
    View Code

    2.一个序列,每次询问一个区间,问这个区间中所有子区间的gcd的乘积。

    注意到一个区间gcd变换到1的总次数不会超过log次,我们首先找到这个区间以及它的gcd的值。之后离线,一个询问可以看成是二维平面中的矩形的元素乘积,而且他们都是紧贴上边界的。

    复杂度O(nlogn^2)。

      1 #pragma GCC optimize 2
      2 #define mod 998244353
      3 #include<bits/stdc++.h>
      4 using namespace std;
      5 typedef long long int ll;
      6 const int maxn=4E5+5;
      7 int n,m,a[maxn];
      8 ll ans[maxn];
      9 inline int read()
     10 {
     11     char ch=getchar();
     12     while(!isdigit(ch))ch=getchar();
     13     int s=ch-'0';ch=getchar();
     14     while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
     15     return s;
     16 }
     17 int G[55];
     18 inline void write(int x)
     19 {
     20     int g=0;
     21     do{G[++g]=x%10;x/=10;}while(x);
     22     for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('
    ');
     23 }
     24 int gcd(int x,int y)
     25 {
     26     return x%y==0?y:gcd(y,x%y);
     27 }
     28 inline ll qpow(ll x,int y)
     29 {
     30     ll ans=1,base=x;
     31     while(y)
     32     {
     33         if(y&1)
     34             ans=ans*base%mod;
     35         base=base*base%mod;
     36         y>>=1;
     37     }
     38     return ans;
     39 }
     40 ll t[maxn*4],tag[maxn*4];
     41 void build(int l,int r,int num)
     42 {
     43     tag[num]=t[num]=1;
     44     if(l==r)
     45         return;
     46     int mid=(l+r)>>1;
     47     build(l,mid,num<<1),build(mid+1,r,num<<1|1);
     48 }
     49 inline void putTag(int num,ll x,int len)
     50 {
     51     t[num]=t[num]*qpow(x,len)%mod;
     52     tag[num<<1]=tag[num<<1]*x%mod;
     53     tag[num<<1|1]=tag[num<<1|1]*x%mod;
     54 }
     55 inline void pushdown(int num,int len)
     56 {
     57     ll x=tag[num];
     58     tag[num]=1;
     59     if(x==1)
     60         return;
     61     putTag(num,x,len);
     62 }
     63 inline void pushup(int num)
     64 {
     65     t[num]=t[num<<1]*t[num<<1|1]%mod;
     66 }
     67 void change(int L,int R,int l,int r,ll x,int num)
     68 {
     69     pushdown(num,r-l+1);
     70     if(L<=l&&r<=R)
     71     {
     72         putTag(num,x,r-l+1);
     73         return;
     74     }
     75     int mid=(l+r)>>1;
     76     if(R<=mid)
     77         change(L,R,l,mid,x,num<<1);
     78     else if(mid<L)
     79         change(L,R,mid+1,r,x,num<<1|1);
     80     else
     81         change(L,R,l,mid,x,num<<1),change(L,R,mid+1,r,x,num<<1|1);
     82     pushup(num);
     83 }
     84 ll ask(int L,int R,int l,int r,int num)
     85 {
     86     pushdown(num,r-l+1);
     87     if(L<=l&&r<=R)
     88         return t[num];
     89     int mid=(l+r)>>1;
     90     if(R<=mid)
     91         return ask(L,R,l,mid,num<<1);
     92     else if(mid<L)
     93         return ask(L,R,mid+1,r,num<<1|1);
     94     return ask(L,R,l,mid,num<<1)*ask(L,R,mid+1,r,num<<1|1)%mod;
     95 }
     96 struct line
     97 {
     98     int l,r,x;
     99     line(int a=0,int b=0,int c=0):l(a),r(b),x(c){}
    100 }S[maxn];
    101 int tot;
    102 struct query
    103 {
    104     int x,l,r,id,type;
    105     bool operator<(const query&A)const
    106     {
    107         return x>A.x;
    108     }
    109 }Q[maxn*2];
    110 void out(int l,int r,int num)
    111 {
    112     pushdown(num,r-l+1);
    113     if(l==r)
    114     {
    115         cout<<t[num]<<" ";
    116         return;
    117     }
    118     int mid=(l+r)>>1;
    119     out(l,mid,num<<1),out(mid+1,r,num<<1|1);
    120 }
    121 inline void solve()
    122 {
    123     sort(Q+1,Q+tot+1);
    124     build(1,n,1);
    125     int top=0;
    126     int pos=1;
    127     while(Q[pos].x==n+1)
    128         ++pos;
    129     for(int i=n;i>=1;--i)
    130     {
    131         S[++top]=line(i,i,a[i]);
    132         for(int j=top-1;j>=1;--j)
    133         {
    134             S[j].x=gcd(S[j].x,S[j+1].x);
    135             if(S[j].x==S[j+1].x)
    136             {
    137                 S[j].l=S[j+1].l;
    138                 for(int k=j+1;k<=top;++k)
    139                     S[k]=S[k+1];
    140                 --top;
    141             }
    142         }
    143         for(int i=1;i<=top;++i)
    144             change(S[i].l,S[i].r,1,n,S[i].x,1);
    145         while(Q[pos].x==i)
    146         {
    147             int id=Q[pos].id;
    148             if(Q[pos].type)
    149                 ans[id]=ans[id]*qpow(ask(Q[pos].l,Q[pos].r,1,n,1),mod-2)%mod;
    150             else
    151                 ans[id]=ans[id]*ask(Q[pos].l,Q[pos].r,1,n,1)%mod;
    152             ++pos;
    153         }
    154     }
    155 }
    156 int main()
    157 {
    158     freopen("easy.in","r",stdin);
    159     freopen("easy.out","w",stdout);
    160     ios::sync_with_stdio(false);
    161     n=read(),m=read();
    162     for(int i=1;i<=n;++i)
    163         a[i]=read();
    164     for(int i=1;i<=m;++i)
    165     {
    166         ++tot;
    167         Q[tot].l=read(),Q[tot].r=read();
    168         Q[tot].id=i;
    169         Q[tot].type=0;
    170         Q[tot].x=Q[tot].l;
    171         ++tot;
    172         Q[tot]=Q[tot-1];
    173         Q[tot].type=1;
    174         Q[tot].x=Q[tot].r+1;
    175         ans[i]=1;
    176     }
    177     solve();
    178     for(int i=1;i<=m;++i)
    179         write(ans[i]);        
    180     return 0;
    181 }
    View Code
  • 相关阅读:
    【水】希望之花
    如何不用狄利克雷卷积证明莫比乌斯函数性质二
    【数学】gcd
    挂分宝典
    [luogu P6042]「ACOI2020」学园祭 题解
    [luogu P6041]「ACOI2020」布丁暗杀计划 题解
    11.19模拟
    「CSP-S2020」题解
    11.11模拟
    「洛谷P1445」樱花
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/13025290.html
Copyright © 2011-2022 走看看