Liu_runda 的简单题 随(rand) 倍增优化 概率DP

来源:互联网 发布:sql server 认证 编辑:程序博客网 时间:2024/05/29 04:50

大家都很强, 可与之共勉。

随 (rand)
【题目描述】
给出n个正整数a1,a2…an和一个质数mod.一个变量x初始为1.进行m次操作.每次在n个数中随机选一个ai,然后x=x*ai%mod.问m次操作之后x的取值的期望.
答案一定可以表示成a/b的精确分数形式.a和b可能很大,所以只需要输出a*(b^(10^9+5))模10^9+7的结果.
【输入格式】
第一行三个整数n,m,mod.
接下来一行n个空格隔开的正整数a1,a2…an
【输出格式】
一行一个整数表示答案
【样例输入】
2
1 3 1 2
【样例输出】
3
【数据范围】
3
第1个测试点:mod=2
第2个测试点:n=1
第3,4,5个测试点:m<=1000,1<=mod<=300.
第6,7,8个测试点:1<=mod<=300
对于全部测试点: 1<=ai < mod,mod为质数1<=mod<=1000,
对于全部测试点:1<=n<=10^5,1<=m<=10^9
【孙金宁教你学数学】
质数P的原根g满足1<=rt < P,且rt的1次方,2次方…(P-1)次方在模P意义下可以取遍1到(P-1)的所有整数.
欧拉定理:对于质数P,1<=x < P的任意x的P-1次方在模P意义下都为1.
显然,原根的1次方,2次方…(P-2)次方在模P意义下都不为1,只有(P-1)次方在模P意义下为1.这也是一个数成为原根的充分必要条件.

不知道这个原根拿来干什么

题解

代码里面很清楚了
复杂度O(logm * mod ^2)

ZJC手把手教你踩std

这是std

oooO ↘┏━┓ ↙ Oooo
( 踩)→┃你┃ ←(死 )
\ ( →┃√┃ ← ) /
  _)↗┗━┛ ↖(_/
 //*/ _ std____
 

# include <bits/stdc++.h># define debug(...) fprintf( stderr, __VA_ARGS__ )# define LocalJudge( File ) freopen ( File ".in", "r", stdin ) ;    freopen ( File ".out", "w", stdout ) ;inline int mpow ( register int a, register int x )  {    register int rt ;    for ( rt = 1 ; x ; x >>= 1, a = 1LL * a * a % 1000000007 )        if ( x & 1 )  {            rt = 1LL * rt * a % 1000000007 ;        }    return rt ;}int a [100010] ;int dp [31] [1010] ;  // Possibility ( after 2 ^ i operation, x == j ) ;int ans [1010], tmp [1010] ;inline bool SPJ2 ( int n )  {    for ( int i = 1 ; i <= n ; ++ i )   if ( a [i] ^ 1 )    return 0 ;    return 1 ;}int main ( )  {    LocalJudge ( "rand" ) ;    int n, m, mod ;    register int i, j, k ;    scanf ( "%d%d%d", & n, & m, & mod ) ;    for ( int i = 1 ; i <= n ; ++ i )   scanf ( "%d", a + i ) ;    /*****************Special Judge Begin****************/    if ( m == 1 )  {        int A ( 0 ) ;        for ( i = 1 ; i <= n ; ++ i )  {            A += ( a [i] % mod ) ;            if ( A >= 1000000007 )  A -= 1000000007 ;        }        return printf ( "%d\n", 1LL * A * mpow ( n, 1000000007 - 2 ) % 1000000007 ), 0 ;     }    if ( SPJ2 ( n ) )   return puts ( "1" ), 0 ;    /******************Special Judge End*****************/    /**************Dynamic Programming Begin*************/    // Initialize dp( 0, 0 to mod - 1 ) ;    for ( i = 1 ; i <= n ; ++ i )   ++ dp [0] [a [i] % mod] ;    const int B = mpow ( n, 1000000007 - 2 ) ;    for ( i = 0 ; i < mod ; ++ i )  dp [0] [i] = 1LL * dp [0] [i] * B % 1000000007 ;    // DP ;    int Logm = log2 ( m ) ;    for ( i = 1 ; i <= Logm ; ++ i )        for ( j = 0 ; j < mod ; ++ j )            for ( k = 0 ; k < mod ; ++ k )  {                int *d = &dp [i] [( j * k ) % mod] ;                *d = ( *d + 1LL * dp [i - 1] [j] * dp [i - 1] [k] % 1000000007 ) % 1000000007 ;             }    /***************Dynamic Programming End**************/    // Merge array ans ;    ans [1] = 1 ;    for ( i = 0 ; i <= Logm ; ++ i )  {        if ( ( 1 << i ) & m )  {            memset ( tmp, 0, sizeof ( int ) * ( mod + 1 ) ) ;  // There must be an array tmp ;            for ( j = 0 ; j < mod ; ++ j )                for ( k = 0 ; k < mod ; ++ k )  {                    int* d = &tmp [( j * k ) % mod] ;                    *d = ( *d + 1LL * ans [j] * dp [i] [k] % 1000000007 ) % 1000000007 ;                }            memcpy ( ans, tmp, sizeof ( int ) * ( mod + 1 ) ) ;        }    }    // Get result ;    int result = 0 ;    for ( i = 0 ; i < mod ; ++ i )  result = ( result + ( 1LL * ans [i] * i ) ) % 1000000007 ;    return printf ( "%d\n", result ), 0 ;}
原创粉丝点击