At300 E - Dice Product 3

E.Dice Product 3


原题链接

题意简述

给定一个初始为 \(1\) 的数,每次掷一个1~6的骰子,在原来的数上乘以骰子上的数,给定一个数 \(n\),掷骰子直到数大于等于 \(n\) 时停止,求最终停止在 \(n\) 的概率,所有数均 取模 \(998244353\)

解题思路1

概率 dp ,推式子 ,显然有\(f[n]=1/6·(f[n]+f[n/2]+f[n/3]+f[n/4]+f[n/5]+f[n/6])\)
移项,化简,得 \(f[n]=1/5·(f[n/2]+f[n/3]+f[n/4]+f[n/5]+f[n/6])\),注意特判是否整除。这个式子的每一项都可以看作 n 继续递归,直到求出 \(1\) 的时候进行返回。因为递归次数的限制,考虑利用 \(map\) 记忆化处理每一次的结果。

AC code1

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const ll mod=998244353;
ll q_pow(ll a,ll b){
    ll s=1LL;
    while(b){
        if(b&1){
            s=s*a%mod;
        }
        a=a*a%mod;
        b>>=1;
    }
    return s;
}
ll p;
map<ll,ll>mp;
ll dfs(ll x){
    if(x==1) return 1;
    if(mp.count(x)) return mp[x];
    ll ans=0;
    if(x%2==0) ans=(ans+dfs(x/2)*p%mod)%mod;
    if(x%3==0) ans=(ans+dfs(x/3)*p%mod)%mod;
    if(x%4==0) ans=(ans+dfs(x/4)*p%mod)%mod;
    if(x%5==0) ans=(ans+dfs(x/5)*p%mod)%mod;
    if(x%6==0) ans=(ans+dfs(x/6)*p%mod)%mod;
    return mp[x]=ans;
}
int main(){
    cin.tie(0)->ios::sync_with_stdio(false);
    ll n;cin>>n;
    p=q_pow(5LL,mod-2);
    cout<<dfs(n)<<endl;
    return 0;
}

解题思路2

本着几乎所有记忆化的搜索都可以改成dp的原则,我们考虑这题的 \(dp\) 形式,发现每次记忆化其实就是对每个因子出现概率做了记录,避免大量重复统计因子的概率。对 n 考虑质因数分解

AC code2

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const ll mod=998244353;
ll q_pow(ll a,ll b){
    ll s=1LL;
    while(b){
        if(b&1){
            s=s*a%mod;
        }
        a=a*a%mod;
        b>>=1;
    }
    return s;
}
ll f[65][65][65];
int main(){
    cin.tie(0)->ios::sync_with_stdio(false);
    ll n;cin>>n;
    ll p=q_pow(5LL,mod-2);
    int _2=0,_3=0,_5=0;
    while(n%2==0) n/=2,++_2;
    while(n%3==0) n/=3,++_3;
    while(n%5==0) n/=5,++_5;
    if(n!=1) return cout<<0<<endl,0;
    f[0][0][0]=1LL;
    for(int i=0;i<=_2;i++){
        for(int j=0;j<=_3;j++){
            for(int k=0;k<=_5;k++){
               (f[i+1][j][k]+=f[i][j][k]*p%mod)%=mod;//2
               (f[i][j+1][k]+=f[i][j][k]*p%mod)%=mod;//3
               (f[i+2][j][k]+=f[i][j][k]*p%mod)%=mod;//4
               (f[i][j][k+1]+=f[i][j][k]*p%mod)%=mod;//5
               (f[i+1][j+1][k]+=f[i][j][k]*p%mod)%=mod;//6
            }
        }
    }
    cout<<f[_2][_3][_5]<<endl;
    return 0;
}
posted @ 2025-06-08 14:46  usedchang  阅读(8)  评论(0)    收藏  举报