第19次CCF计算机软件能力认证-第4题-202006-4 1246

代码取自 躺平的hhy写的文章
在这里插入图片描述在这里插入图片描述

#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define rep(i,start,end) for(int i=start;i<=end;i++)
using namespace std;
typedef long long LL;
typedef pair<LL,LL> pa;
const int mod=998244353;
int x;
string sub;
const int N=14;
int w[N][N];//转移矩阵
int id[100];
vector<int> v{1,2,4,6,16,26,41,42,44,46,61,62,64,66};
vector<vector<int>> vv{
   {2},{4},{1,6,16},{6,4,64},{26},{46},{62},{64},{61},{66},{42},{44},{41},{46}

};

void init()

{
   memset(id,-1,sizeof(id));
   for(int i=0;i<N;i++)
       id[v[i]]=i;
   //求出来转移矩阵
   for(int i=0;i<N;i++){
       for(auto t:vv[i])
           w[i][id[t]]++;
   }

}

void multi(int c[][N],int a[][N],int b[][N])

{
   //求c=a*b
   int tmp[N][N];
   memset(tmp,0,sizeof(tmp));
   for(int i=0;i<N;i++)
       for(int j=0;j<N;j++)
           for(int k=0;k<N;k++)
               tmp[i][j]=(tmp[i][j]+(LL)a[i][k]*b[k][j])%mod;
   memcpy(c,tmp,sizeof(tmp));

}

int qpow(int x,int id)

{
   if(id==-1)return 0;//代表出现不可能的数
   int ans[N][N];
   int tr[N][N];//转移矩阵,因为可能不止一次使用w,所有不可以直接改变w的值
   memset(ans,0,sizeof(ans));
   for(int i=0;i<N;i++)ans[i][i]=1;//单位矩阵
   memcpy(tr,w,sizeof(w));
   while(x){
       if(x&1)multi(ans,ans,tr);
       multi(tr,tr,tr);
       x>>=1;
   }
   return ans[0][id];

}

string get(string str)

{
   string ans;
   int n=str.size();
   for(int i=0;i<n;i++){
       //遍历str的元素
       if(str[i]=='1'){
           if(i+1==n||str[i+1]=='6')ans+='4',i++;//16同时出现。代表上一轮是4
           else return "";
       }
       else if(str[i]=='2')ans+='1';
       else if(str[i]=='4')ans+='2';
       else{
           if(i+1==n||str[i+1]=='4')ans+='6',i++;
           else return "";
       }
   }
   return ans;

}

LL dfs(int x,string&sub)

{
   if(sub.size()<=2)return qpow(x,id[stoi(sub)]);//如果长度小于等于2
   LL res=0;
   for(string s:{"","1","6"}){//可能是完整的,也可能前面少个1 6
       string tmp=get(s+sub);
       if(tmp.size())res=(res+dfs(x-1,tmp))%mod;
   }
   return res;

}

int main()

{
   //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);
   std::ios::sync_with_stdio(false);
   init();
   cin>>x>>sub;
   cout<<dfs(x,sub)<<endl;

}

#include<bits/stdc++.h>
#define mod 998244353
#define ll long long
using namespace std;


ll w[15][15];
int id[70];
string s;


void inital(){

//用于构造转移矩阵===============
vector<int> v{0,1,2,4,6,16,26,41,42,44,46,61,62,64,66};
vector<vector<int>> vv{ {0},
   {2},{4},{1,6,16},{6,4,64},{26},{46},{62},{64},{61},{66},{42},{44},{41},{46}

};
//==================================





for(int i=1;i<=14;++i)
    id[v[i]]=i;


for(int i=1;i<=14;++i)
    for(auto t:vv[i])
        w[i][id[t]]=1;





}


void multi(ll c[][15],ll a[][15],ll b[][15]){
//矩阵相乘c=a*b

//for(int i=1;i<=14;++i){for(int j=1;j<=14;++j)cout<<a[i][j]<<" ";cout<<endl;}

ll tt[15][15];//因为a、b、c数组是传参过来的,有两个数组是同一个数组的情况,
//而在计算中的元素需要复用,直接修改c数组会造成原数据被修改

memset(tt,0,sizeof(tt));




for(int i=1;i<=14;++i)
    for(int j=1;j<=14;++j)
        for(int k=1;k<=14;++k)
            tt[i][j]=(tt[i][j]+(a[i][k]*b[k][j]%mod))%mod;



for(int i=1;i<=14;++i)
    for(int j=1;j<=14;++j)
        c[i][j]=tt[i][j];

//for(int i=1;i<=14;++i){for(int j=1;j<=14;++j)cout<<tt[i][j]<<" ";cout<<endl;}

}



ll qpow(ll x,string ss){
ll ans[15][15];
memset(ans,0,sizeof(ans));
for(int i=1;i<=14;++i)
    ans[i][i]=1;



ll tt[15][15];

for(int i=1;i<=14;++i)
    for(int j=1;j<=14;++j)
        tt[i][j]=w[i][j];






while(x){
    if(x&1) multi(ans,ans,tt);
    multi(tt,tt,tt);
    x>>=1;

}



int stonum=stoi(ss);
return ans[1][id[stonum]];

}


int main(){

std::ios::sync_with_stdio(false);
ll n;
cin>>n>>s;


inital();

cout<<qpow(n,s)<<endl;

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值