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('\n');
 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

 

 posted on 2020-06-01 15:04  GreenDuck  阅读(231)  评论(0编辑  收藏  举报