[来自liu_runda的爱] 随
写在前面:这道题浪费了我很长时间(鬼知道今天的考试难度递减的?)
10分算法:
我们观察这两句话:“第1个测试点:mod=2---对于全部测试点: 1<=ai<mod,mod为质数1<=mod<=1000”,这说明什么?说明mod==2时a[]全为1啊!
于是直接输出1即可,10分就开心地(于学长.pdf)拿到了。
20分算法:
n==1时用快速幂即可,结合上述算法,20分拿到。
50分算法:
设f[i][j]为进行完i个操作后为j的概率,于是就有:
(f[i][j]+=f[i-1][j*a[k]%p]*S%mod)%=mod;
其实可以把把没个数的贡献放到一个桶里,这样复杂度就从O(n*m*mod)变为了O(n*mod*mod),在3,4,5测试点没给n范围的情况下法二显然更稳。
80分算法:
是个蜜汁算法:达哥题解说要用矩阵优化,但是复杂度O(mod^3*log2(m))我是过不去6,7,8测试点的~
但可以去问问kx大神https://www.cnblogs.com/hzoi-kx/
100分算法:
前置知识:原根(上网搜总能找到的)。
有了这个知识之后我们便可以依靠原根把乘法转换为加法了,
f[i][j]代表操作了2^i次的结果是原根的i次方的方案数,用倍增的思想O(mod^2*log2(m))转移即可
for(int i=1;i<=35;i++)
{
for(int j=0;j<p;j++)
{
for(int k=0;k<p;k++)
{
(f[(j+k)%(p-1)][i]+=f[j][i-1]*f[k][i-1]%mod)%=mod;
}
}
}
之后我们考虑如何把m拆开统计答案,
我原来想的是简单的模数一样的简单相加,但是不然,
以为这样相当于统计的是2^1, 2^3.....的答案累加,也就是说好几次操作分开进行。
所以是错的,正解是像预处理f数组一样处理,期望得分100分