Processing math: 100%

dtoj3226荒芜废墟(ruins)

荒芜废墟(ruins)

 Ori来到了荒芜废墟,荒芜废墟可以看成一条数轴。Ori一开始在 0 ,每一次可以往右跳 k 的步。但有些位置设置了激光,这些位置Ori是无法到达的,一共有 m 种激光,每一种激光有一个特征值 ti 表示这种激光会出现在 ti 以及 ti 的倍数的位置上。Ori想要知道从 0 走到 n 有多少种走法。


对于100%的数据, n109m3k50 ,保证ti,k可以写成 2a3b 的形式,其中 a,b5


 Sol

n是1e9,我们考虑矩乘来转移。

注意到 2a3b3125 

也就是说ti和k的lcm最多3125,记为T

前k步的转移是有限制的,不能从转i<0转,需要特殊处理

处理完我们就T步T步的转移,每T步的转移都是相同的。

最后一段也暴力转移即可。

复制代码
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define mod 1000000007
using namespace std;
int n,m,k,t[4],T; 
ll f[55],F[8005],a[8500][55];
struct node{
    ll v[52][52];
}p,ans;
node ch(node a,node b){
    node c;
    for(int i=0;i<k;i++)
    for(int j=0;j<k;j++){
        c.v[i][j]=0;
        for(int x=0;x<k;x++){
            c.v[i][j]=(c.v[i][j]+a.v[i][x]*b.v[x][j]%mod)%mod;
        }
    }
    return c;
}
int main(){

    cin>>n>>m>>k;T=k;
    for(int i=1;i<=m;i++){
        scanf("%d",&t[i]);
        T=T*t[i]/__gcd(T,t[i]);
    }
    f[0]=1;a[0][0]=1;
    for(int i=1;i<=k-1;i++){
        a[i][i]=1;
        for(int j=i-1;j>=0;j--){
            f[i]=(f[i]+f[j])%mod;
        }
        for(int x=1;x<=m;x++)if(i%t[x]==0)f[i]=0;
    }
    for(int i=k;i<T+k;i++){
        for(int j=i-1;j>=i-k;j--){
            int fl=0;for(int x=1;x<=m;x++)if(j%t[x]==0)fl=1;
            if(fl&&j)continue;
            for(int x=0;x<k;x++){
                a[i][x]=(a[i][x]+a[j][x])%mod;
            }
        }
        for(int j=1;j<=m;j++){
            if(i%t[j]==0)for(int x=0;x<k;x++)a[i][x]=0;
        }
    }
    for(int i=T;i<T+k;i++){
        for(int j=0;j<k;j++)p.v[j][i-T]=a[i][j];
        ans.v[i-T][i-T]=1;
    }
    int num=n/T;n%=T;
    while(num){
        if(num&1)ans=ch(ans,p);
        p=ch(p,p);num>>=1;
    }
    for(int i=0;i<k;i++){
        for(int j=0;j<k;j++){
            F[i]=(F[i]+ans.v[j][i]*f[j]%mod)%mod;
        }
    }
    for(int i=k;i<=n;i++){
        for(int j=i-1;j>=i-k;j--){
            F[i]=(F[i]+F[j])%mod;
        }
        for(int x=1;x<=m;x++)if(i%t[x]==0)F[i]=0;
    }
    cout<<F[n]<<endl;
    
    return 0;
}
复制代码

 

posted @   liankewei123456  阅读(311)  评论(0编辑  收藏  举报
编辑推荐:
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
阅读排行:
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· PPT革命!DeepSeek+Kimi=N小时工作5分钟完成?
· What?废柴, 还在本地部署DeepSeek吗?Are you kidding?
· 赶AI大潮:在VSCode中使用DeepSeek及近百种模型的极简方法
· DeepSeek企业级部署实战指南:从服务器选型到Dify私有化落地
历史上的今天:
2019-02-17 [NOI2014]动物园
2019-02-17 最大异或和(xor)
2019-02-17 排序
点击右上角即可分享
微信分享提示