【动态规划】【SDOI2017】序列计数
【动态规划】【SDOI2017】序列计数
题目描述
Alice 想要得到一个长度为
Alice 还希望,这
Alice 想知道,有多少个序列满足她的要求。
算法概述
先不考虑质数的限制,对第一条限制做
设
其中
同理,考虑质数限制,设
其中
发现
考虑从
初始矩阵为
如果不清楚为什么是这样,建议将两个矩阵手模一下,观察乘法过程。
根据补集转化,至少有一个质数的答案就是
Code
#include<bits/stdc++.h>
using namespace std;
const int N = 2e6 + 5,MOD = 20170408;
int prime[N],cnt = 0,p,cntf[105],cntg[105],m,n;
typedef long long ll;
ll f[105],g[105];
bitset <N * 10> vis;
inline void init()
{
cntf[1]++;cntg[1]++;
for(int i = 2;i <= m;i++)
{
cntf[i % p]++;
if(!vis[i]) prime[++cnt] = i;
else cntg[i % p]++;
for(int j = 1;j <= cnt && 1ll * i * prime[j] <= m;j++)
{
vis[i * prime[j]] = 1;
if(!(i % prime[j])) break;
}
}
}
struct Matrix {
ll a[105][105];
};
Matrix operator *(Matrix x,Matrix y)
{
Matrix z;
memset(z.a,0,sizeof(z.a));
for(int i = 0;i <= p - 1;i++)
for(int j = 0;j <= p - 1;j++)
for(int k = 0;k <= p - 1;k++)
z.a[i][j] = (z.a[i][j] + x.a[i][k] * y.a[k][j] % MOD) % MOD;
return z;
}
inline Matrix ksm(Matrix base,int pts)
{
Matrix ret;
memset(ret.a,0,sizeof(ret.a));
for(int i = 0;i <= p - 1;i++) ret.a[i][i] = 1;
for(;pts > 0;pts >>= 1,base = base * base)
if(pts & 1)
ret = ret * base;
return ret;
}
int main()
{
cin>>n>>m>>p;
init();
Matrix kf,kg;
for(int i = 0;i <= p - 1;i++)
for(int j = 0;j <= p - 1;j++)
kf.a[i][j] = cntf[(j - i + p) % p],kg.a[i][j] = cntg[(j - i + p) % p];
kf = ksm(kf,n - 1);
kg = ksm(kg,n - 1);
for(int i = 0;i <= p - 1;i++)
for(int j = 0;j <= p - 1;j++)
f[i] = (f[i] + cntf[j] * kf.a[j][i] % MOD) % MOD,g[i] = (g[i] + cntg[j] * kg.a[j][i] % MOD) % MOD;
cout<<(f[0] - g[0] + MOD) % MOD;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话