AT_abs300_e 题解

发布时间 2023-04-29 22:30:22作者: trh0630

一、题目描述:

  你有一个骰子,数字 1~6 可以被等概率扔到。

  初始时有一个数 $ans=1$。

  当扔到数字 $x$ 时,$ans=ans \times x$。

  给你一个数字 $n$ ,求 $ans$ 能等于 $n$ 的概率。

  $n<=1e18$。答案对 $998244353$ 取模。


 二、解题思路:

  当扔到 $1$ 时,相当于没扔,所以可以视为 5 个数

  求出 $n$ 的质因数 $2$,$3$,$5$ 的个数,设有 $ans_2$ 个$2$,$ans_3$ 个$3$,$ans_5$ 个$5$。

  一个 $6$ 相当于一个 $2$ 和一个 $3$ 相乘,一个 $4$ 相当于两个 $2$ 相乘。

  枚举 $4$ 的数量,再枚举 $6$ 的数量,再套组合数板子:多重集的排列数量。

  最后求和。需要用到逆元,阶乘。时间复杂度O($log^3n$),可以通过。

三、完整代码:


 1 #include<iostream>
 2 #define ll long long
 3 #define mod 998244353
 4 using namespace std;
 5 ll n,t2=1,rans,jc[100];
 6 ll ans2,ans3,ans5;
 7 ll qsm(ll base,ll p)
 8 {
 9     ll ans=1;
10     while(p)
11     {
12         if(p&1)    ans*=base,ans%=mod;
13         base*=base,base%=mod,p>>=1;
14     }
15     return ans;
16 }
17 int main()
18 {
19     cin>>n;jc[0]=1;
20     while(n&&n%2==0)
21         ans2++,n/=2;
22     while(n&&n%3==0)
23         ans3++,n/=3;
24     while(n&&n%5==0)
25         ans5++,n/=5;
26     if(n!=1)
27     {
28         cout<<0<<'\n';
29         return 0;
30     }
31     for(ll i=1;i<=70;i++)
32         jc[i]=jc[i-1]*i%mod;
33     for(ll i=0;i<=min(ans2,ans3);i++)
34         for(int j=0;j*2<=ans2-i;j++)
35         {
36             ll t=ans2+ans3+ans5-i-j;
37             t2=jc[t]*qsm(qsm(5,t),mod-2)%mod;
38             t2*=qsm(jc[i],mod-2),t2%=mod;
39             t2*=qsm(jc[j],mod-2),t2%=mod;
40             t2*=qsm(jc[ans5],mod-2),t2%=mod;
41             t2*=qsm(jc[ans3-i],mod-2),t2%=mod;
42             t2*=qsm(jc[ans2-i-j*2],mod-2),t2%=mod;
43             
44             rans+=t2,rans%=mod;
45         }
46     cout<<rans<<'\n';
47     return 0;
48 }

四、写题心得:

  很好的一道题,对我来说有难度。这次是完全自己想出来的,很高兴,可惜是在比赛后十分钟写出来的 qwq!不过还是加油吧!拜拜!