| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> CCF CSP 1246 100分题解(c++) -> 正文阅读 |
|
[C++知识库]CCF CSP 1246 100分题解(c++) |
这道题难度挺大的,尤其是最后一个点。 首先观察数据点,前24个点数字串s的长度是1或2, 其次n特别大 ,肯定是要用到快速幂的,CCF CSP不止一次考过快速幂 当s的长度为1或2时,通过简单的排列组合知识也知道,s的情况并不多,我们可以直接枚举转移方程,转移方程如下。 显然我们需要矩阵快速幂。 当s的长度为1或2时,s的情况只有以上14种 我们构造转移矩阵的时候,可以考虑将这些点离散化,即只构造一个14*14的转移矩阵 按照这十四个离散的值从小到大,分别映射成0到13. 只要转移矩阵给出来了,套下矩阵快速幂的板子,前96分就到手了。 重点是最后四分。 根据y总的视频讲解,当s的长度大于2时,我们可以根据转移的规律,逆推到s只有两位的情况。 s是由什么转移过来的呢? s在整个序列的情况,可能分为s前面是1,s前面是6,或者s前面不是1或6. 它对应的转移情况不尽相同 下列代码中的get的函数,是求s上一层是由什么转移过来的。 如果不存在转移到s的上一层,则返回空串。 如果存在,就递归查找,直到查找到上一层的长度是2. 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"}){// ????????string?tmp=get(s+sub); ????????if(tmp.size())res=(res+dfs(x-1,tmp))%mod; ????} ????return?res; } 完整代码如下 #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; } |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/28 12:01:18- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |