CSP 模拟题 1246

题意:

 

部分分:

|S|=1 :

送分快速幂

|S|=2 :

给所有可能的两个数字组合(有序)编上号,用 0x 表示x在左边界, x0表示x在右边界,放入一个矩阵内, x,y  向 2^x 的最小位 , 2^y 的最高位转移,所有以4 6为开头的状态向1,6  6,4转移,用矩阵快速幂即可

|S|>2

我们可以发现,给定一个序列,如果我们确定了开头和结尾的一或两位是由哪个数变换成的,我们就可以将整个序列倒推回n-1时的状态。 每个序列最多有四种可能,

仔细看样例会发现当n减少的时候序列的长度减少的速度也很快,且还有可能存在无解的情况,所以通过搜索将|S|化成长度为1或2再计算即可。

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<cmath>
  7 #define N 30
  8 using namespace std;
  9 int n,l;
 10 const int p=998244353;
 11 char aa[100005];
 12 struct no{
 13     int n,m;
 14     long long a[N][N];
 15 }A,B,ans;
 16 int dl[N][N],cnt,b[10],a[201][100006],c[100005];
 17 int get_l(int x)
 18 {
 19     if(!x)return 0;
 20     if(x<4) return pow(2,x);
 21     return (pow(2,x))/10;
 22 }
 23 int get_r(int x)
 24 {
 25     if(!x)return 0;
 26     if(x<4)return pow(2,x);
 27     return (int)(pow(2,x))%10;
 28 }
 29 void work(no &A,no B)
 30 {
 31     ans.n=A.n,ans.m=A.m;
 32     for(int i=1;i<=A.n;i++)
 33         for(int j=1;j<=A.m;j++) ans.a[i][j]=0;
 34     for(int i=1;i<=ans.n;i++)
 35     {
 36         for(int j=1;j<=cnt;j++)
 37         {
 38             for(int k=1;k<=cnt;k++)
 39             {
 40                 ans.a[i][j]+=1ll*A.a[i][k]*B.a[k][j]%p;
 41             }
 42             ans.a[i][j]%=p;
 43         }
 44     }
 45     A=ans;
 46 }
 47 void ksm(int z,no A,no B)
 48 {
 49     while(z)
 50     {
 51         if(z&1) work(A,B);
 52         work(B,B);
 53         z>>=1;
 54     }
 55     ans.n=A.n,ans.m=A.m;
 56     for(int i=1;i<=ans.n;i++)
 57         for(int j=1;j<=ans.m;j++)
 58             ans.a[i][j]=A.a[i][j];
 59 }
 60 int work2(int L,int dp)
 61 {
 62     int cnt1=0;
 63     a[dp][L+1]=0;
 64     for(int i=1;i<=L;i++)
 65     {
 66         if(a[dp][i]==1||a[dp][i]==6)
 67         {
 68             if(a[dp][i]==1)
 69             {
 70                 if(a[dp][i+1]!=6) return -1;
 71                 else
 72                 {
 73                     cnt1++;
 74                     c[cnt1]=4;
 75                 }
 76             }
 77             else
 78             {
 79                 if(a[dp][i+1]!=4) return -1;
 80                 else
 81                 {
 82                     cnt1++;
 83                     c[cnt1]=6;
 84                 }
 85             }
 86             i++;
 87         }
 88         else
 89         {
 90             cnt1++;
 91             if(a[dp][i]==2) c[cnt1]=1;
 92             else c[cnt1]=2;
 93         }
 94     }
 95     return cnt1;
 96 }
 97 void work3(int L);
 98 void dfs(int L,int n,int dp);
 99 void work3(int L,int n,int dp)
100 {
101     int tmp=work2(L,dp);
102     if(tmp!=-1)
103     {
104         for(int i=1;i<=tmp;i++) a[dp+1][i]=c[i];
105         dfs(tmp,n,dp+1);
106     }
107 }
108 long long sum;
109 void dfs(int L,int n,int dp)
110 {
111     if(n<0)return;
112     if(L<=2)
113     {
114         ksm(n,A,B);
115         if(L==1)
116         {
117             for(int i=1;i<=5;i++)
118             {
119                 sum+=ans.a[1][dl[a[dp][1]][b[i]]];
120                 sum%=p;
121             }
122         }
123         else
124         {
125             int x=a[dp][1],y=a[dp][2];
126             sum+=ans.a[1][dl[x][y]];
127             sum%=p;
128         }
129     }
130     else
131     {
132         
133         
134         if(a[dp][1]==6||a[dp][1]==4)
135         {
136             for(int i=L;i;i--)
137                 a[dp][i+1]=a[dp][i];
138             if(a[dp][1]==6) a[dp][1]=1;
139             else a[dp][1]=6;
140             if(a[dp][L+1]==1||a[dp][L+1]==6)
141             {
142                 if(a[dp][L+1]==1) a[dp][L+2]=6;
143                 else a[dp][L+2]=4;
144                 work3(L+2,n-1,dp);
145                 a[dp][L+2]=0;
146             }
147             work3(L+1,n-1,dp);
148             for(int i=1;i<=L;i++) a[dp][i]=a[dp][i+1];
149             a[dp][L+1]=0;
150         }
151         if(a[dp][L]==1||a[dp][L]==6)
152         {
153             if(a[dp][L]==1) a[dp][L+1]=6;
154             else a[dp][L+1]=4;
155             work3(L+1,n-1,dp);
156             a[dp][L+1]=0;
157         }
158         work3(L,n-1,dp);
159     }
160 }
161 int main()
162 {
163     scanf("%d",&n);
164     scanf("%s",aa+1);
165     l=strlen(aa+1);
166     for(int i=1;i<=l;i++) a[0][i]=aa[i]-'0';
167     b[1]=1;
168     b[2]=2;
169     b[3]=4;
170     b[4]=6;
171     b[5]=0;
172     for(int i=1;i<=5;i++)
173     {
174         for(int j=1;j<=5;j++)
175         {
176             cnt++;
177             dl[b[i]][b[j]]=cnt;
178         }
179     }
180     for(int i=1;i<=5;i++)
181     {
182         for(int j=1;j<=5;j++)
183         {
184             int x,y;
185             x=b[i],y=b[j];
186             B.a[dl[x][y]][dl[get_r(x)][get_l(y)]]++;
187             if(x==4||x==6)
188                 B.a[dl[x][y]][dl[get_l(x)][get_r(x)]]++;
189         }
190     }
191     B.n=B.m=cnt;
192     A.n=1,A.m=cnt;
193     A.a[1][dl[0][1]]=A.a[1][dl[1][0]]=1;
194     dfs(l,n,0);
195     printf("%lld\n",sum);
196     return 0;
197 }
View Code
posted @ 2020-09-05 21:23  Hzoi_joker  阅读(915)  评论(0编辑  收藏  举报