[CF1097D]Makoto and a Blackboard
作者:互联网
题目
点这里看题目。
分析
设 \(f_k(n)\) 表示经过了 \(k\) 次操作之后 \(n\) 的期望。
这里有一个很重要的性质:\(f\) 是积性函数。
事实上,每次操作就相当于是对 \(n\) 的每一个质因子 \(p_i\) 的指数 \(k_i\) 随机替换为 \([0,k_i]\) 中的一个整数。可以发现各个质因子之间不相干。或者说:
\[\begin{aligned}E(n)&=\sum_{\{k'_i\}}[\forall i,0\le k'_i\le k_i]\prod_{i}\frac{1}{k_i+1}\prod_i p_i^{k'_i}\\&=\sum_{i}\sum_{k'=0}^{k_i} \frac{1}{k_i+1}p_i^{k'}\end{aligned} \]现在我们就可以将 \(n\) 按照质因子拆开。此时我们只需要求 \(p_i^0,p_i^1,p_i^2,...,p_i^{k_i}\) 的最终出现概率即可。
由于底数相等,现在我们对指数进行 DP 。状态:
\(g(t,j)\) :经过了前 \(j\) 次操作之后,出现 \(p_i^t\) 的概率。
转移略。此时 \(p_i\) 的贡献就是 \(\sum_{k'}f(k',k)\times p_i^{k'}\) 。
小结:
- 将原先的整个数拆分成各个质因子,并利用积性简化成单个质因子的问题,遇到因子相关的问题会很有用。多多观察题目的结果是否具有积性。
- 在底数确定的时候直接处理指数,比较常见的技巧。有时候还可以发现它不受 \(k_i\) 的约束,就可以预处理。
代码
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
const int MAXN = 1e4 + 5, MAXS = 100;
template<typename _T>
void read( _T &x )
{
x = 0; char s = getchar(); int f = 1;
while( s < '0' || '9' < s ) { f = 1; if( s == '-' ) f = -1; s = getchar(); }
while( '0' <= s && s <= '9' ) { x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar(); }
x *= f;
}
template<typename _T>
void write( _T x )
{
if( x < 0 ) putchar( '-' ), x = -x;
if( 9 < x ) write( x / 10 );
putchar( x % 10 + '0' );
}
template<typename _T>
_T MAX( const _T a, const _T b )
{
return a > b ? a : b;
}
int f[MAXS], inv[MAXS];
int ind[MAXN];
LL prim[MAXN], pn;
LL N; int K, lim;
int Qkpow( int, int );
inline int Mul( LL x, int v ) { return x * v % mod; }
inline int Inv( const int a ) { return Qkpow( a, mod - 2 ); }
inline int Sub( int x, int v ) { return ( x -= v ) < 0 ? x + mod : x; }
inline int Add( int x, int v ) { return ( x += v ) >= mod ? x - mod : x; }
int Qkpow( int base, int indx )
{
int ret = 1;
while( indx )
{
if( indx & 1 ) ret = Mul( ret, base );
base = Mul( base, base ), indx >>= 1;
}
return ret;
}
void PFactorize( LL n )
{
for( LL i = 2 ; i * i <= n ; i ++ )
if( ! ( n % i ) )
{
prim[++ pn] = i;
while( ! ( n % i ) )
ind[pn] ++, n /= i;
}
if( n > 1 ) prim[++ pn] = n, ind[pn] = 1;
}
int Calc( LL p, const int x )
{
for( int i = 0 ; i <= x ; i ++ ) f[i] = 0;
f[0] = 1; int tmp;
for( int k = 1 ; k <= K ; k ++ )
for( int i = x ; ~ i ; i -- )
{
tmp = 0;
for( int j = i ; ~ j ; j -- )
tmp = Add( tmp, Mul( inv[x - j + 1], f[j] ) );
f[i] = tmp;
}
int ret = 0, pw = 1; p %= mod;
for( int i = 0 ; i <= x ; i ++, pw = Mul( pw, p ) )
ret = Add( ret, Mul( pw, f[x - i] ) );
return ret;
}
int main()
{
read( N ), read( K );
PFactorize( N ); int ans = 1;
for( int i = 1 ; i <= pn ; i ++ ) lim = MAX( lim, ind[i] );
for( int i = 1 ; i <= lim + 1 ; i ++ ) inv[i] = Inv( i );
for( int i = 1 ; i <= pn ; i ++ ) ans = Mul( ans, Calc( prim[i], ind[i] ) );
write( ans ), putchar( '\n' );
return 0;
}
标签:Makoto,const,int,Blackboard,LL,base,return,CF1097D,mod 来源: https://www.cnblogs.com/crashed/p/14079590.html