2019牛客多校训练(五)

比赛链接:

https://ac.nowcoder.com/acm/contest/885#question

B.generator 1

题意:

求出类似斐波那契数列的第$n$项

$n\leq  10^{10^{6}}$

分析:

我想着欧拉降幂。。。其实欧拉降幂并不适用于矩阵的运算

队友看了题之后立马想到十进制的矩阵快速幂,太强了

和普通的矩阵不同的是,这个每次乘十前进,但这不是问题

对矩阵快速幂的时间复杂度认识得不深,潜意识以为$n$是一个无穷大的数

ac代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e6 + 5;
struct Maritx
{
    ll num[3][3];
}s;
int mod,x0,x1;
char in[maxn];
Maritx mul(Maritx a,Maritx b)
{
    Maritx res;
    res.num[1][1]=res.num[2][2]=0;
    res.num[1][2]=res.num[2][1]=0;
    for(int i=1;i<=2;i++)
        for(int j=1;j<=2;j++)
            for(int k=1;k<=2;k++)
                res.num[i][j]=(res.num[i][j]+a.num[i][k]*b.num[k][j]%mod)%mod;
    return res;
}
int main()
{
    scanf("%d %d %lld %lld",&x0,&x1,&s.num[1][1],&s.num[1][2]);
    scanf("%s %d",in+1,&mod);
    int len=strlen(in+1);
    s.num[2][1]=1;
    s.num[2][2]=0;
    Maritx ans;
    ans.num[1][1]=ans.num[2][2]=1;
    ans.num[1][2]=ans.num[2][1]=0;
    for(int i=len;i>=1;i--){
        int v=in[i]-'0';
        Maritx temp=s;
        for(int j=1;j<=9;j++){
            if(j==v)ans=mul(ans,s);
            s=mul(s,temp);
        }
    }
    printf("%d\n",(ans.num[2][1]*x1%mod+ans.num[2][2]*x0%mod)%mod);
    return 0;
}

G.subsequence 1

题意:

给出$s$和$t$两个字符串,计算$s$的子串数量,十进制形式大于$t$字符串

分析:

定义$dp[i][j][k]$,考虑$s$的$i$个字符,组成长度为$j$的子串中,$k=0$小于$t$的前$j$位,$k=1$等于$t$的前$j$位,$k=2$大于前$j$位的数量

ac代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 3e3 + 5;
const ll mod =  998244353;
ll dp[maxn][maxn][3];
char s[maxn],t[maxn];
int main()
{
    int T,n,m;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&m);
        scanf("%s %s",s+1,t+1);
        if(n<m){
            printf("0\n");
            continue;
        }
        for(int i=1;i<=n;i++){
            dp[i][1][0]=dp[i-1][1][0];
            dp[i][1][1]=dp[i-1][1][1];
            dp[i][1][2]=dp[i-1][1][2];
            if(s[i]!='0'){
                if(s[i]>t[1])dp[i][1][2]=(dp[i][1][2]+1)%mod;
                else if(s[i]==t[1])dp[i][1][1]=(dp[i][1][1]+1)%mod;
                else if(s[i]<t[1])dp[i][1][0]=(dp[i][1][0]+1)%mod;
            }
            for(int j=2;j<=min(n,i);j++){
                    dp[i][j][0]=dp[i-1][j][0];
                    dp[i][j][1]=dp[i-1][j][1];
                    dp[i][j][2]=dp[i-1][j][2];
                if(j<=m){
                    if(s[i]==t[j]){
                        dp[i][j][0]=(dp[i][j][0]+dp[i-1][j-1][0])%mod;
                        dp[i][j][1]=(dp[i][j][1]+dp[i-1][j-1][1])%mod;
                        dp[i][j][2]=(dp[i][j][2]+dp[i-1][j-1][2])%mod;
                    }else if(s[i]<t[j]){
                        dp[i][j][2]=(dp[i][j][2]+dp[i-1][j-1][2])%mod;
                        dp[i][j][0]=(dp[i][j][0]+dp[i-1][j-1][1]+dp[i-1][j-1][0])%mod;
                    }else {
                        dp[i][j][0]=(dp[i][j][0]+dp[i-1][j-1][0])%mod;
                        dp[i][j][2]=(dp[i][j][2]+dp[i-1][j-1][2]+dp[i-1][j-1][1])%mod;
                    }
                }else{
                    dp[i][j][2]=(dp[i][j][2]+dp[i-1][j-1][0]+dp[i-1][j-1][1]+dp[i-1][j-1][2])%mod;
                }
            }
        }


        ll ans=0;
        for(int i=m;i<=n;i++)ans=(dp[n][i][2]+ans)%mod;
        printf("%lld\n",ans);
        for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)dp[i][j][0]=dp[i][j][1]=dp[i][j][2]=0;
    }
    return 0;
}

  

 

猜你喜欢

转载自www.cnblogs.com/carcar/p/11296417.html
今日推荐