这个题的题解并不想写……一个写的很详细的blog

第1个测试点:mod=2,a[i]<mod(仔细看题),则n个数字都是1,直接输出1即可.

第2个测试点:每次乘上去的数字只有一种选择,快速幂即可.

第3,4,5个测试点:定义f[i][j]表示i次操作后x的数值为j的概率.直接转移,复杂度O(m*mod^2)

         f[][]=;
for(int i=;i<m;i++)
for(int j=;j<mod;j++)
for(int k=;k<mod;k++)//这里不要枚举n啊,可以先处理出来每个数出现的概率
f[i+][j*k%mod]=(f[i+][j*k%mod]+f[i][j]*v[k]%p)%p;

第6,7,8个测试点:第3,4,5个测试点中的DP转移可以转化为矩阵乘法形式,利用矩阵快速幂进行优化,复杂度O(mod^3*logm)矩阵快速幂优化dp见--->这里

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define int LL
#define MAXN 100010
#define LL long long
using namespace std;
struct jz
{
LL m[][];
void clear(){memset(m,,sizeof(m));}
}base;
int n,m,mod,a[MAXN];
const int p=1e9+;
jz operator * (jz &a,jz &b)
{
jz ans;ans.clear();
for(int i=;i<mod;i++)
for(int j=;j<mod;j++)
for(int k=;k<mod;k++)
ans.m[i][j]=(ans.m[i][j]+a.m[i][k]*b.m[k][j]);
for(int i=;i<mod;i++)
for(int j=;j<mod;j++)
ans.m[i][j]%=p;
return ans;
}
jz operator ^ (jz a,int b)
{
jz ans=a;b--;
while(b)
{
if(b&)ans=ans*a;
a=a*a;
b=b>>;
}
return ans;
}
LL f[][],tem;
LL v[];
LL poww(LL a,int b,int mod)
{
LL ans=;
while(b)
{
if(b&)ans=ans*a%mod;
a=a*a%mod;
b=b>>;
}
return ans;
}
signed main()
{
// freopen("in.txt","r",stdin);
// freopen("0.out","w",stdout); cin>>n>>m>>mod;tem=poww(n,p-,p);
for(int i=;i<=n;i++)cin>>a[i],v[a[i]%mod]=(v[a[i]%mod]+tem)%p;
if(mod==){puts("");return ;}
if(n==){printf("%lld\n",poww(a[],m,mod));return ;}
if(m<=)
{
f[][]=;
for(int i=;i<m;i++)
for(int j=;j<mod;j++)
for(int k=;k<mod;k++)
f[i+][j*k%mod]=(f[i+][j*k%mod]+f[i][j]*v[k]%p)%p;
LL ans=;
for(int i=;i<mod;i++)
ans=(ans+f[m][i]*i%p)%p;
printf("%lld\n",ans%p);
}
else if(mod<=)
{
for(int j=;j<mod;j++)
for(int k=;k<mod;k++)
base.m[j*k%mod][j]=(base.m[j*k%mod][j]+v[k])%p;
base=base^m;
LL ans=;
for(int i=;i<mod;i++)
ans=(ans+base.m[i][]*i%p)%p;
printf("%lld\n",ans%p);
}
}

这里放出暴力dp和矩阵优化dp

第9,10个测试点(标算):上面那个blog讲的非常详细了(然而我并没有看懂……),总感觉这个矩阵优化dp怪怪的……

先把达哥题解放出来:

利用原根进行转化,则乘法转化为加法,f[i][j]表示i次操作后x取模后等于原根的j次方的概率.指数需要对(mod-1)取模.这样转化一下我们发现转移还是矩阵的形式,而且是循环矩阵的形式.循环矩阵快速幂,复杂度O(mod^2*logm)

然后是另一种标算(本人写的这个):

定义f[i][j]表示i次操作后变成原根的j次方的概率.求出p[i][j]表示2^i次操作后变成原根的j次方的概率.倍增的思想求出f[m][]这个数组.也是O(mod^2*logm)

     for(int i=;i<=mod-;i++)p[][i]=tem*cnt[i]%mp;//乘2^0为rt^i的概率,tem为分母的逆元,cnt为个数。
for(int i=;i<=;i++)
for(int j=;j<=mod-;j++)
for(int k=;k<=mod-;k++)
p[i][(j+k)%(mod-)]=(p[i][(j+k)%(mod-)]+p[i-][j]*p[i-][k]%mp)%mp;

然后用类似快速幂的方法就可以求出了,避免了直接理解矩阵。

 #include<iostream>
#include<cstdio>
#define MAXN 400010
#define LL long long
#define int LL
using namespace std;
const int mp=1e9+;
int n,m,mod,a[MAXN];
int xp[],cnt[];
int rt;
int p[][],f[][];
LL poww(LL a,int b,int mod)
{
LL ans=;
while(b)
{
if(b&)ans=ans*a%mod;
a=a*a%mod;
b=b>>;
}
return ans;
}
void findroot()
{
for(rt=;rt<mod;rt++)
{
bool pd=;
for(int i=;i<mod-;i++)
if(poww(rt,i,mod)==){pd=;break;}
if(pd||poww(rt,mod-,mod)!=)continue;
else break;
}
}
signed main()
{
cin>>n>>m>>mod;
findroot();int tem=poww(n,mp-,mp),x;
xp[]=;for(int i=;i<=mod;i++)xp[i]=xp[i-]*rt%mod;
for(int i=;i<=mod-;i++)a[xp[i]]=i;
for(int i=;i<=n;i++)cin>>x,cnt[a[x]]++;
for(int i=;i<=mod-;i++)p[][i]=tem*cnt[i]%mp;//乘2^0为rt^i的概率;
for(int i=;i<=;i++)
for(int j=;j<=mod-;j++)
for(int k=;k<=mod-;k++)
p[i][(j+k)%(mod-)]=(p[i][(j+k)%(mod-)]+p[i-][j]*p[i-][k]%mp)%mp;
f[][]=;
for(int k=;m;m/=,k++)
if(m&)
{
for(int i=;i<=mod-;i++)f[][i]=;
for(int i=;i<=mod-;i++)
for(int j=;j<=mod-;j++)
f[][(j+i)%(mod-)]=(f[][(j+i)%(mod-)]+f[][i]*p[k][j]%mp)%mp;
for(int i=;i<=mod-;i++)f[][i]=f[][i];
}
LL ans=;
for(int i=;i<=mod-;i++)ans=(ans+f[][i]*xp[i]%mp)%mp;
printf("%lld\n",ans);
}

完整代码

更加优越的算法(???):本质上我们要做的是循环卷积,可以使用fft.但本题的模数使得fft较为不方便..

HZOJ 随的更多相关文章

  1. hzoj 2301(莫比乌斯反演)

    题意 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公 数. 思路: 与先前的那个相比,这次a,c并不一定 ...

  2. HZOJ 单

    两个子任务真的是坑……考试的时候想到了60分的算法,然而只拿到了20分(各种沙雕错,没救了……). 算法1: 对于测试点1,直接n遍dfs即可求出答案,复杂度O(n^2),然而还是有好多同学跑LCA/ ...

  3. 20191102 「HZOJ NOIP2019 Round #12」20191102模拟

    先开坑. md原题写挂我也真是... 100+20+10 白夜 打表大法吼 显然,不在环上的点对答案的贡献是 \((k-cycle)^{k-1}\) . 打表得到环上的递推式,矩阵一下乘起来就好了. ...

  4. 20191004 「HZOJ NOIP2019 Round #9」20191004模拟

    综述 第一次 rk1 ,激动. 题目是 COCI 18/19 Round #1 的三至五题. 得分 \(100+100+20\) \(\mathrm{cipele}\) 问题描述 HZOJ1313 题 ...

  5. 20191003 「HZOJ NOIP2019 Round #8」20191003模拟

    综述 试题为常州集训2019SCDay2 得分\(100+30(0)+28\) 时之终结 问题描述 HZOJ1310 题解 构造题. 发现部分分有一档是 \(Y\) 是 \(2^x\) ,于是自然想到 ...

  6. 20190922 「HZOJ NOIP2019 Round #7」20190922模拟

    综述 这次是USACO2019JAN Gold的题目. \(\mathrm{Cow Poetry}\) 题解 因为每句诗的长度一定是\(k\),所以自然而然想到背包. 设\(opt[i][j]\)代表 ...

  7. HZOJ 20190819 NOIP模拟26题解

    考试过程: 照例开题,然后觉得三道题都挺难,比昨天难多了(flag×1),T1 dp?T2 数据结构? T3 dp?事实证明我是sb然后决定先搞T2,但是,woc,这题在说什么啊,我怎么看不懂题啊,连 ...

  8. HZOJ 20190818 NOIP模拟24题解

    T1 字符串: 裸的卡特兰数题,考拉学长讲过的原题,就是bzoj3907网格那题,而且这题更简单,连高精都不用 结论$C_{n+m}^{n}-C_{n+m}^{n+1}$ 考场上10min切掉 #in ...

  9. HZOJ 20190727 随(倍增优化dp)

    达哥T1 实际上还是挺难的,考试时只qj20pts,还qj失败 因为他专门给出了mod的范围,所以我们考虑把mod加入时间复杂度. $50\%$算法: 考虑最暴力的dp,设$f[i][j]$表示进行$ ...

  10. HZOJ 20190727 T2 单(树上dp+乱搞?+乱推式子?+dfs?)

    考试T2,考试时想到了40pts解法,即对于求b数组,随便瞎搞一下就oxxk,求a的话,很明显的高斯消元,但考试时不会打+没开double挂成10pts(我真sb),感觉考试策略还是不够成熟,而且感觉 ...

随机推荐

  1. java实体类的属性名首字母不能大写,不然el表达式无法取值

    摘要:Java命名规范中,实体类属性名以小写字母开头,但并没有说不能以大写字母开头,然而事实告诉我,大写真不行 https://www.cnblogs.com/jnhs/p/10025757.html

  2. request.setCharacterEncoding("utf-8");

    request.setCharacterEncoding("utf-8");不加这句话时,从input控件得到值要用new String(request.getParameter( ...

  3. oracle习题练习-表空间-用户-表-约束

    题一 1.       创建名字为hy_tablespace的表空间,默认大小为10M;@@ 2.       创建一个用户,用户名以自己名字命名,并指定命名空间为hy_tablespace;@@@@ ...

  4. django中静态资源

    创建静态资源存放路径,为了设置静态媒体,你需要设立存储它们的目录.在你的项目目录(例如/myproject/),创建叫做static的目录.在static里再创建一个images目录和js目录 设置项 ...

  5. JavaScript的注意事项

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. HR招聘_(九)_招聘方法论(面试环节·薪资谈判和心理把控)

    .薪资谈判 薪资谈判在整个过程中非常重要,如果这一环出现问题前期的所有付出都功亏一篑,无法达成招聘目标. 谈判过程中需要遵循以下原则: 明确 通过面试后需要再次确认候选人的目前薪资和期望,虽然第一次电 ...

  7. Mac 下终端命令行之基本命令总结(持续更新)

    最近用Mac做一些开发,用到了一些命令行的内容,先将常用的命令行进行总结.由于会不断的用到新的,所以将会持续的总结进来.每一个命令行的使用可能都会比较复杂,我只会总结最常用的使用方法. echo命令 ...

  8. 转搞定python多线程和多进程

    转自https://www.cnblogs.com/whatisfantasy/p/6440585.html 1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小 ...

  9. [转] javascript核心

    原文:http://dmitrysoshnikov.com/ecmascript/javascript-the-core/ 对象 原型链 构造函数 执行上下文栈 执行上下文 变量对象 活动对象 作用域 ...

  10. Leetcode788.Rotated Digits旋转数字

    我们称一个数 X 为好数, 如果它的每位数字逐个地被旋转 180 度后,我们仍可以得到一个有效的,且和 X 不同的数.要求每位数字都要被旋转. 如果一个数的每位数字被旋转以后仍然还是一个数字, 则这个 ...