集训7.24

A. midpoint displacement

题目描述

midpoint displacement算法是一种能够用于生成一维噪声的算法。
通俗地讲,你有一个长度为2^n+1的数组,初始时给你两端的权值,你要随机性地给每个下标赋一个权值,最终这个数组在统计学上会有一些优秀的性质。直观地讲,如果把权值视为高度的话,他会较为平滑而又有所起伏,仿佛层峦叠嶂在你眼前。
整个算法由若干次midpoint displacement不断进行来构成。
在一次midpoint displacement中,对于除了最后一个下标外的每一个已经被赋值的下标i,找到他后面第一个已经被赋值的下标j,将i和j的中点的权值设为i的权值与j的权值的平均数+一个随机数(可能为负,假设范围为[-lim,lim])
每进行一次midpoint displacement,随机数的范围lim就会缩小一倍。
当所有下标都被赋值,算法结束。
为了测评方便,避免随机化与浮点数,在本题中使用光老犇随机器,一定会随机到最大的数,同时不取平均数,而是直接作和。也就是说,在midpoint displacement的时候,我们令中点的权值等于两端的权值的和加上lim,模1e9+7。并且,每进行完一次midpoint displacement,我们将lim乘以2,并模1e9+7
在样例解释中你可以得到详细的解释。
现在给定n,初始时两端的权值,以及随机数的初始范围,请计算最终每个点的权值和模1e9+7

输入格式

一行4个整数,分别代表n,左端权值,右端权值,随机数的初始范围

输出格式

一行一个整数,代表最终所有元素的和模1e9+7

样例

样例输入:
3 1 1 1
样例输出:
65

样例解释:
n=3,所以数组长度为2^n+1=9
最终数组如下:
1 11 6 13 3 13 6 11 1
初始时左右两端为1,lim=1
下标从1开始
a[5]=a[1]+a[9]+lim=3
lim=lim2=2
a[3]=a[1]+a[5]+lim=6
a[7]=a[5]+a[9]+lim=6
lim=lim
2=4
a[2]=a[1]+a[3]+lim=11
a[4]=a[3]+a[5]+lim=13
a[6]=a[5]+a[7]+lim=13
a[8]=a[7]+a[9]+lim=11
所有点都被赋值,算法结束。
所有元素和为65

提示:请注意你的程序在进行连续加法时是否会超出int型整数的范围

数据范围与提示

对于所有数据,0<=两端权值、lim<=32767

测试点1,n<=23, a[1]=a[2^n+1]=lim=0 测试点2,n<=3
测试点3,n<=3
测试点4,n<=3
测试点5,n<=16
测试点6,n<=16
测试点7,n<=16
测试点8,n<=23
测试点9,n<=23
测试点10 ,n<=23

我的代码

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#define mod 1000000007
using namespace std;
long long poww(int p,int q)
{
 long long ans=1;
 int base=p;
 while(q!=0)
 {
  if((q&1)!=0)
  {
   ans=ans*base;
   ans=ans%mod;
  }
  base=base*base;
  base=base%mod;
  q=q>>1;
 }
 return ans;
}
int main()
{
 freopen("midpointdisplacement.in","r",stdin);
 freopen("midpointdisplacement.out","w",stdout);
 int n,l,r,lim;
 scanf("%d%d%d%d",&n,&l,&r,&lim);
 long long a=(poww(3,n)+1)/2;
 a=a%mod;
 long long b=poww(4,n)-poww(3,n);
 b=b%mod;
 long long ans=(a*l%mod+a*r%mod+b*lim%mod)%mod;
 cout<<ans;
 return 0;
}
我可能是找规律找错了,只得了40分

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值