zoukankan      html  css  js  c++  java
  • 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
    ",sum);
    196     return 0;
    197 }
    View Code
  • 相关阅读:
    随手快递app冲刺2开发的第六天
    随手快递app冲刺2开发的第五天
    随手快递app冲刺2开发的第四天
    随手快递app冲刺2开发的第三天
    随手快递appc冲刺2开发的第二天
    随手快递app冲刺2开发的第一天
    程序员修炼之道:从小工到专家阅读笔记03
    安卓学习70
    安卓学习69
    安卓学习68
  • 原文地址:https://www.cnblogs.com/liutianrui/p/13619771.html
Copyright © 2011-2022 走看看