bzoj 2655: calc
来源:互联网 发布:sublime php错误提示 编辑:程序博客网 时间:2024/05/29 15:00
题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2655
思路:
算法一:
A<=10,n<=10
注意到n和A都很小直接枚举每一位是什么就行了
时间复杂度:
期望得分:5
算法二:
n和A都不太大,考虑dp
注意到我们可以将一个合法解排序,只需计算严格递增序列的答案最后乘上n!即可
期望得分:20
算法三:
我们发现A很大,相比之下n是很小的
考虑倍增优化算法二
设
预处理组合数等,很容易
倍增求出
复杂度:
期望得分:70—100
算法五:
考虑暴力dp
设f[i]表示i个数时的答案
转移?
容斥原理
无限制乘积 - 至少有一个重复的 + 至少有两个重复的 - ····
复杂度:
期望得分:100分
ps:一开始组合数写错了,身败名裂
其实还有一种有关多项式的做法:
xiaoyimi大爷的做法:
从原始dp的思路出发
f[i][j]表示i个元素中选取j个的分数
写出dp方程
初始状态
手玩j比较小的情况,容易发现,
那也就是说我们最终的答案
这是个很好的性质,因为我们只用求出
那这个系数怎么求呢?
有一种比较容易想到的方法是求出较小的
但这样的复杂度是
所以我们尝试引入拉格朗日插值法
设
其中
同样是求出
理论复杂度为
但实际上是可以做到
容斥原理:
#include<iostream>#include<cstdio>#include<cstring>#include<string>#define N 505using namespace std;typedef long long LL;LL A,n,P,g[N + 5],f[N + 5],sum[N + 5],c[N + 5][N + 5],fact[N + 5],inv[N + 5];int main(){ //freopen("calc20.in","r",stdin); //freopen("calc20.out","w",stdout); cin>>A>>n>>P; memset(f,0,sizeof(f)); f[0] = 1; f[1] = (A * (A + 1)>>1) % P; inv[1] = 1; for (int i = 2;i <= n + 5; ++i) inv[i] = (P - P/i) * inv[P % i] % P; fact[0] = 1; for (int i = 1;i <= n + 5; ++i) fact[i] = i * fact[i - 1] % P; for (int i = 0;i <= n + 5; ++i) c[i][0] = 1; for (int i = 1;i <= n + 5; ++i) for (int j = 1;j <= i; ++j) c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % P; g[0] = (A + 1)%P; g[1] = (A * (A + 1)>>1) % P; LL pow = (A + 1) * (A + 1) % P; for (int i = 2;i <= n; ++i){ pow = pow * (A + 1) % P; LL sum = (A + 1) % P; for (int j = 1;j < i; ++j) sum = (sum + c[i + 1][j] * g[j] % P) % P; sum = (pow - sum)%P; if (sum < 0) sum += P; g[i] = inv[i + 1] * sum % P; } for (int i = 2;i <= n; ++i){ f[i] = g[1] * f[i - 1] % P; LL op = -1; for (int j = i - 2;j >= 0; --j){ f[i] = (f[i] + op * fact[i - 1 - j] % P * c[i - 1][i - 1 - j] % P * g[i - j] % P * f[j] % P + P) % P; op = -op;} } cout<<f[n]; // fclose(stdin); fclose(stdout); return 0;}
1.推导的时候要仔细,不能胡乱推啊,不要总是自以为什么,要考虑式子的意义,从多方面考虑
- bzoj 2655: calc
- BZOJ 2655 calc
- bzoj 2655: calc dp+拉格朗日插值法
- bzoj 2506 calc 题解
- BZOJ 2506 calc
- BZOJ 2671 Calc 数论
- 【BZOJ 2671】Calc
- bzoj 2671: Calc 数学
- 2655: calc
- 2655: calc
- BZOJ 2671(Calc-数论反演)
- BZOJ 2506: calc【离线,值域分块
- BZOJ 2506: calc 权值分块
- calc
- Calc
- calc()
- calc.exe
- 10calc
- js-js基础之数据类型
- Java多线程学习(吐血超详细总结)
- Android ListView功能扩展,实现高性能的瀑布流布局
- javascript函数
- 开始写技术博客
- bzoj 2655: calc
- Genymotion解决VirtualBox cannot start the virtual device
- 设计模式之 : 工厂模式
- Android--Android的网络通信机制
- lightoj 1147 - Tug of War
- mongodb 统计内嵌文档中某一属性的方法
- 冒泡排序(数组实现)
- Android基础入门教程——9.2 MediaPlayer播放音频与视频
- Hive中的join