分类
标签
2-SAT AC自动机 BFS CDQ dfs DP fail树 FFT FFT&NTT FWT hash KD-Tree KMP LCA SPFA STL Tarjan Treap Trie 主席树 乱搞 二分 二分图匹配 二分答案 二维SPFA 交互 位运算 其他 最小生成树 分块 区间DP 半平面交 博弈论 可持久化 可持久化Trie树 后缀数组 图库 平衡树 并查集 插头DP 数学 数论 无旋Treap 日记 暴力 权值树状数组 栈 树DP 树套树 树状数组 树贪心 概率DP 模拟 欧拉定理 点分治 状压DP 生成函数 矩阵乘 线性规划 线段树 组合 网络流 群论 莫比乌斯反演 计算几何 贪心 费用流 高斯消元
788 字
4 分钟
BZOJ 2510 弱题
Description
有M个球,一开始每个球均有一个初始标号,标号范围为1~N且为整数,标号为i的球有ai个,并保证Σai = M。 每次操作等概率取出一个球(即取出每个球的概率均为1/M),若这个球标号为k(k < N),则将它重新标号为k + 1;若这个球标号为N,则将其重标号为1。(取出球后并不将其丢弃) 现在你需要求出,经过K次这样的操作后,每个标号的球的期望个数。
Input
第1行包含三个正整数N,M,K,表示了标号与球的个数以及操作次数。 第2行包含N个非负整数ai,表示初始标号为i的球有ai个。
Output
应包含N行,第i行为标号为i的球的期望个数,四舍五入保留3位小数。
Sample Input
2 3 2
3 0
Sample Output
1.667
1.333
HINT
【样例说明】
第1次操作后,由于标号为2球个数为0,所以必然是一个标号为1的球变为标号为2的球。所以有2个标号为1的球,有1个标号为2的球。
第2次操作后,有1/3的概率标号为2的球变为标号为1的球(此时标号为1的球有3个),有2/3的概率标号为1的球变为标号为2的球(此时标号为1的球有1个),所以标号为1的球的期望个数为1/33+2/31 = 5/3。同理可求出标号为2的球期望个数为4/3。
【数据规模与约定】
对于10%的数据,N ≤ 5, M ≤ 5, K ≤ 10;
对于20%的数据,N ≤ 20, M ≤ 50, K ≤ 20;
对于30%的数据,N ≤ 100, M ≤ 100, K ≤ 100;
对于40%的数据,M ≤ 1000, K ≤ 1000;
对于100%的数据,N ≤ 1000, M ≤ 100,000,000, K ≤ 2,147,483,647。
题解
一看k的范围
就能看出要矩阵乘优化
易得矩阵为
然后我们发现n=1000过不了
但是我们发现这个矩阵是一个循环矩阵
只用维护第一行就可以了
降低到 就可以跑了
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
struct Martix
{
double a[1005];
int n;
Martix(int x)
{
n = x;
memset(a, 0, sizeof(a));
}
Martix operator*(const Martix &b)
{
Martix ans(n);
ans.a[1] = 0;
for (int i = 1; i <= n; i++)
{
for (int k = 1; k <= n; k++)
{
int t=(i-k+n+1)%n;
if(!t) t+=n;
ans.a[i] += a[k] * b.a[t];
}
}
return ans;
}
Martix operator^(const int x)
{
Martix a = *this, ans(n);
int k = x;
ans.a[1] = 1;
while (k)
{
if (k & 1)
ans = ans * a;
k >>= 1;
a = a * a;
}
return ans;
}
};
int a[1005];
double ans[1005];
int main(int argc, char const *argv[])
{
int n, m, k;
scanf("%d%d%d",&n,&m,&k);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
Martix K(n);
K.a[1] = (double)1 - ((double)1 / m);
K.a[2] = ((double)1 / m);
K=K^k;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
int t=(i+j-1)%n;
if(!t) t+=n;
ans[t] += K.a[i] * a[j];
}
}
for (int i = 1; i <= n; i++)
{
printf("%.3lf\n", ans[i]);
}
//while(1);
return 0;
}