分析:
看到k的范围真的大,所以以为要用矩阵乘法,但是1000*1000不是矩阵乘法的数据范围
所以打了个20分就跑了
40%
实际上,由期望的线性性我们可以得到每个跳跃点的期望计算公式:
多么简单的一个公式啊,我们就可以直接模拟,40分到手
70%
我们把进行完一轮后每只青蛙的位置看做是一个序列
虽然k非常大,但是跳跃后能形成的序列个数是达不到1e18级别的
也就是说,序列存在循环节
我们只要找到这个循环节,剩下的几轮暴力模拟即可
看来70分好像也很好拿,还是自己不够认真,不过这个循环节的思路很妙啊
看了一下队友的实现方法,有hash,也有直接比较
//胖爷的code,感觉还是比较优美的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
long long t[100010],d[100010],a[100010],k;
int check()
{
for(int i=1;i<=n;i++)
if(a[i]!=d[i]) return 1;
return 0;
}
int main()
{
freopen("frog.in","r",stdin);
freopen("frog.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
d[i]=a[i];
}
scanf("%d%lld",&m,&k);
for(int i=1;i<=m;i++)
scanf("%lld",&t[i]);
int now=0;
do
{
now++;
for(int i=1;i<=m;i++)
a[t[i]]=a[t[i]-1]+a[t[i]+1]-a[t[i]];
}
while(check()&&now!=k);
if(now==k)
{
for(int i=1;i<=n;i++)
printf("%lld\n",a[i]);
return 0;
}
k%=now;
while(k--)
for(int i=1;i<=m;i++)
a[t[i]]=a[t[i]-1]+a[t[i]+1]-a[t[i]];
for(int i=1;i<=n;i++)
printf("%lld\n",a[i]);
}
100%
可以发现每次跳跃后有
也就是说,每次两个差分交换了位置(
xi+1−xi<=>xi−xi−1
x
i
+
1
−
x
i
<=>
x
i
−
x
i
−
1
)
那么一轮就是对差分做了一个置换,要求这个置换的k次幂
我们找到这个置换的每个轮换,对于每个轮换记录k次之后的状态
这样我们就得到了最终的差分序列了,最后还原原序列即可
时间复杂度
O(n)
O
(
n
)
tip
最后的答案要开ll
这道题真的提醒我:对待任何一道题都不能浅尝辄止,一定要好好考虑
概率期望题还是要优先考虑公式
#include<cstdio>
#include<cstring>
#include<iostream>
#define ll long long
using namespace std;
const double eps=1e-7;
const int N=100005;
int n,m,a[N],d[N],p[N],ans[N];
bool vis[N];
ll k;
int main()
{
freopen("frog.in","r",stdin);
freopen("frog.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&d[i]);
for (int i=n;i>=1;i--) d[i]=d[i]-d[i-1];
scanf("%d%lld",&m,&k);
for (int i=1;i<=n;i++) p[i]=i;
for (int i=1;i<=m;i++) {
int x;
scanf("%d",&x);
swap(p[x],p[x+1]); //x[i]-x[i-1]=x[i+1]-x[i];
}
for (int i=1;i<=n;i++)
if (!vis[i]) {
int cnt=0;
a[cnt++]=i; //记录轮换中的元素
vis[i]=1;
int t=p[i];
while (t!=i) {
a[cnt++]=t;
vis[t]=1;
t=p[t];
}
for (int i=0;i<cnt;i++)
ans[a[i]]=a[((ll)i+k)%cnt]; //a[i]的差分
}
ll sum=d[1];
printf("%lld\n",sum);
for (int i=2;i<=n;i++) printf("%lld\n",sum+=d[ans[i]]);
return 0;
}