题目描述

给出$n$个正整数$a_1,a_2...a_n$和一个质数mod。一个变量$x$初始为$1$。进行$m$次操作.每次在$n$个数中随机选一个$a_i$,然后$x=x\times a_i$.问$m$次操作之后$x$的取值的期望。答案一定可以表示成$\frac{a}{b}$的精确分数形式。$a$和$b$可能很大,所以只需要输出$a\times b^{{10}^9+5}$模${10}^9+7$的结果。


输入格式

第一行三个整数$n,m,mod$。
接下来一行$n$个空格隔开的正整数$a_1,a_2...a_n$。


输出格式

一行一个整数表示答案。


样例

样例输入

2 1 3
1 2

样例输出

500000005


数据范围与提示

第$1$个测试点:$mod=2$。
第$2$个测试点:$n=1$。
第$3,4,5$个测试点:$m\leqslant 1,000,1\leqslant mod \leqslant 300$。
第$6,7,8$个测试点:$1\leqslant mod \leqslant 300$。
对于全部测试点:$1\leqslant a_i <mod,mod$为质数$1\leqslant mod \leqslant 1,000,1\leqslant n\leqslant {10}^5,1\leqslant m\leqslant {10}^9$。


吕老师教你学数学
质数$P$的原根$g$满足$1\leqslant rt<P$,且$rt$的$1$次方,$2$次方$...(P-1)$次方在模$P$意义下可以取遍$1$到$(P-1)$的所有整数。
欧拉定理:对于质数$P,1\leqslant x<P$的任意$x$的$(P-1)$次方在模$P$意义下都为$1$。
显然,原根的$1$次方,$2$次方$...(P-2)$次方在模$P$意义下都不为$1$,只有$(P-1)$次方在模$P$意义下为$1$。
这也是一个数成为原根的充分必要条件。


题解

第$1$个测试点:

$mod=2$,不要慌,不用考虑$mod$完会有$0$的情况,因为$1\leqslant a_i <mod$,于是$a_i$一定是$1$,所以$x$就是$1$,直接$puts("1");return 0;$就好了。

期望得分:$10$分,共$10$分。

第$2$个测试点:

$n=1$,因为每次只能选这一个数,所以快速幂直接搞就好了。

期望得分:$10$分,共$20$分。

第$3,4,5$个测试点:

考虑$DP$,定义$dp[i][j]$表示第$i$次操作后$x$为$j$的概率。

那么我们能写出$DP$式子:$dp[i][j\times a[k]\% mod]=\sum \limits_{k=1}^ndp[i-1][[j]$。

时间复杂度:$\Theta (n\times m\times mod)$。

但是注意到$3,4,5$这三个测试点并没有对$n$的范围加以约束,所以显然会$T$飞起,那么我们考虑优化这个$DP$。

接着注意$1\leqslant a_i <mod$,所以一共最多会有$mod-1$种不同的$a_i$,试图从这里入手。

开一个数组$sum[i]$记录$i$这个数出现的次数。

那么$DP$式子即可转化为:$dp[i][j\times k\%mod]=\sum \limits_{k=0}^{mod-1}dp[i-1][j]\times sum[k]$。

时间复杂度:$\Theta (m\times {mod}^2)$。

期望得分:$30$分$(RE)$,共$50$分。

如果你说你不希望$RE$,那么你可以把上面$dp$的第一维滚起来。

期望得分:$30$分$(TLE)$,共$50$分。

第$6,7,8$个测试点:

考虑对上面的算法进行优化,$m$很大,考虑矩阵快速幂。

时间复杂度:$\Theta ({mod}^3\times \log m)$。

期望得分:$60$分,共$80$分。

第$9,10$个测试点:

考虑对第$3,4,5$个测试点的$DP$进行优化,还是从$m$下手。

根据上面的$DP$式子可得:$dp[2\times i][j\times k\% mod]=\sum \limits_{j=0}^{mod-1}\sum \limits_{k=0}^{mod-1}dp[i][j]\times dp[i][k]$。

接着使用滚动数组,快速幂求解即可。


代码时刻

$30$分解法(非滚动):

#include<bits/stdc++.h>
using namespace std;
int n,m,mod;
long long sum[1001];
long long fz,fm,ans;
long long dp[1001][1001];
long long qpow(long long x,long long y)
{
long long res=1;
while(y)
{
if(y&1)res=(res*x)%1000000007;
x=(x*x)%1000000007;
y>>=1;
}
return res;
}
int main()
{
scanf("%d%d%d",&n,&m,&mod);
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
sum[x]++;
}
dp[0][1]=1;
for(int i=1;i<=m;i++)
for(int j=0;j<mod;j++)
for(int k=0;k<mod;k++)
dp[i][j*k%mod]=(dp[i][j*k%mod]+dp[i-1][j]*sum[k]%1000000007)%1000000007;
for(int i=0;i<mod;i++)
fz=(fz+dp[m][i]*i%1000000007)%1000000007;
fm=qpow(n,m);
fm=qpow(fm,1000000005);
ans=fz*fm%1000000007;
printf("%lld",ans);
return 0;
}

$30$分解法(滚动):

#include<bits/stdc++.h>
using namespace std;
int n,m,mod;
long long sum[1001];
long long ans;
long long dp[2][1001];
long long qpow(long long x,long long y)
{
long long res=1;
while(y)
{
if(y&1)res=(res*x)%1000000007;
x=(x*x)%1000000007;
y>>=1;
}
return res;
}
int main()
{
scanf("%d%d%d",&n,&m,&mod);
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
sum[x]++;
}
dp[0][1]=1;
for(int i=1;i<=m;i++)
{
memset(dp[i&1],0,sizeof(dp[i&1]));
for(int j=0;j<mod;j++)
for(int k=0;k<mod;k++)
dp[i&1][j*k%mod]=(dp[i&1][j*k%mod]+dp[i&1^1][j]*sum[k]%1000000007)%1000000007;
}
for(int i=0;i<mod;i++)
ans=(ans+dp[m&1][i]*i%1000000007)%1000000007;
printf("%lld",ans*qpow(qpow(n,m),1000000005)%1000000007);
return 0;
}

$100$分解法:

#include<bits/stdc++.h>
using namespace std;
int n,m,mod;
long long dp[2][100001],dp03[2][100001];
bool p,q;
long long ans;
long long qpow(long long x,long long y)
{
long long res=1;
while(y)
{
if(y&1)res=(res*x)%1000000007;
x=(x*x)%1000000007;
y>>=1;
}
return res;
}
void judge()
{
q^=1;
memset(dp03[q],0,sizeof(dp03[q]));
for(int i=0;i<mod;i++)
for(int j=0;j<mod;j++)
dp03[q][1LL*i*j%mod]=(dp03[q][1LL*i*j%mod]+dp03[q^1][i]*dp03[q^1][j]%1000000007)%1000000007;
}
int main()
{
scanf("%d%d%d",&n,&m,&mod);
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
dp03[0][x]++;
}
dp[0][1]=1;
long long inv=qpow(qpow(n,m),1000000005)%1000000007;
while(m)
{
if(m&1)
{
p^=1;
memset(dp[p],0,sizeof(dp[p]));
for(int i=0;i<mod;i++)
for(int j=0;j<mod;j++)
dp[p][1LL*i*j%mod]=(dp[p][1LL*i*j%mod]+dp[p^1][i]*dp03[q][j]%1000000007)%1000000007;
}
m>>=1;
judge();
}
for(int i=0;i<mod;i++)
ans=(ans+i*dp[p][i])%1000000007;
ans=(ans*inv)%1000000007;
printf("%lld",ans);
return 0;
}

rp++

[CSP-S模拟测试]:随(快速幂+数学)的更多相关文章

  1. Rightmost Digit(快速幂+数学知识OR位运算) 分类: 数学 2015-07-03 14:56 4人阅读 评论(0) 收藏

    C - Rightmost Digit Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit ...

  2. 1282 - Leading and Trailing ---LightOj1282(快速幂 + 数学)

    http://lightoj.com/volume_showproblem.php?problem=1282 题目大意: 求n的k次方的前三位和后三位数然后输出 后三位是用快速幂做的,我刚开始还是不会 ...

  3. zhx's contest (矩阵快速幂 + 数学推论)

    zhx's contest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) To ...

  4. lightoj1281快速幂+数学知识

    https://vjudge.net/contest/70017#problem/E 后半部分快速幂就能求出来,要注意03lld不然001是输出错误为1.前半部分用log10() 对于给定的一个数n, ...

  5. noip-2006普及组-数列- 【模拟-找规律-快速幂】

    链接:https://ac.nowcoder.com/acm/contest/153/1047 来源:牛客网 题目描述 给定一个正整数k( ≤ k ≤ ),把所有k的方幂及所有有限个互不相等的k的方幂 ...

  6. LightOJ 1070 Algebraic Problem:矩阵快速幂 + 数学推导

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1070 题意: 给你a+b和ab的值,给定一个n,让你求a^n + b^n的值(MOD ...

  7. HDU 3117 Fibonacci Numbers( 矩阵快速幂 + 数学推导 )

    链接:传送门 题意:给一个 n ,输出 Fibonacci 数列第 n 项,如果第 n 项的位数 >= 8 位则按照 前4位 + ... + 后4位的格式输出 思路: n < 40时位数不 ...

  8. [CSP-S模拟测试]:次芝麻(数学)

    题目描述 小$K$和小$X$都是小次货.身为小次货,最重要的事情就是次啦!所以他们正在纠结如何分芝麻次.一开始,小$K$有$n$个芝麻,小$X$有$m$个芝麻.因为他们都想次更多芝麻,所以每次手中芝麻 ...

  9. 【洛谷P1962 斐波那契数列】矩阵快速幂+数学推导

    来提供两个正确的做法: 斐波那契数列双倍项的做法(附加证明) 矩阵快速幂 一.双倍项做法 在偶然之中,在百度中翻到了有关于斐波那契数列的词条(传送门),那么我们可以发现一个这个规律$ \frac{F_ ...

随机推荐

  1. Mac-peizhi

    ##1-JMeter4export JMETER_HOME=/Users/wulei/softwares/installedsoftwares/apache-jmeter-4.0export CLAS ...

  2. 【监控笔记】【2.4】SQL Server中的 Ring Buffer 诊断各种系统资源压力情况

    SQL Server 操作系统(SQLOS)负责管理特定于SQL Server的操作系统资源. 其中相关的动态管理试图sys.dm_os_ring_buffers将被标识为仅供参考.不提供支持.不保证 ...

  3. JAVA基础--JAVA 集合框架(泛型、file类)

    一.集合总结 集合:Collection体系.Map体系. Collection体系:单列集合的共性操作规则. List:列表,可以重复,有下标,拥有特有的迭代器ListIterator. Array ...

  4. C++自学教程第一课——你好世界,我是柠檬鲸。

    C++系列教程现在在自己学校的一个博客平台发布,几个朋友一起搭建的 [C++基础教程系列](https://blog.ytmaxoj.org/cpp_basic_liuary-0/) 下面是原来的正文 ...

  5. kafka复习(2)

    一.简介 --------------------------------------- 1.kafka是一个分布式的.可分区的.可复制的消息系统.它提供了消息系统的功能,但是有自己独特的设计. 2. ...

  6. 富文本编辑器Ueditor

    一.大概使用: 官网:http://ueditor.baidu.com/website/download.html 使用:[参考index.html] 3.1 引入ueditor的js <scr ...

  7. Codeforces Round #426 (Div. 2) - C

    题目链接:http://codeforces.com/contest/834/problem/C 题意:两个在玩一个游戏,对于每一轮,选定一个自然是k,初始两人的分数都为1,每一个回合赢的人在他当前分 ...

  8. mock.js模拟ajax数据请求

    在我们开发过程中存在着前端页面ui完成了,但是没有接口进行联调数据的情况,现在介绍一下用mock.js来完成数据的请求.这样在后期我们的后台接口完成后只需要更改请求的接口名字即可!前提是你的模拟字段名 ...

  9. 2019长安大学ACM校赛网络同步赛 M LCM (数论)

    链接:https://ac.nowcoder.com/acm/contest/897/M来源:牛客网 LCM 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65 ...

  10. GUI学习之十二——QTextEdit学习总结

    在学习了QFrame和QAbstractScrollArea两个父类后,接下来是一个重头戏:QTextEdit. 一.QTextEdit特性 QTextEdit是一个高级的WYSIWYG(What Y ...