思路:首先每个蚂蚁移速相同,而且碰到就转头,这其实等价于擦肩而过!
看到2n个数互不相同就觉得方便多了:枚举每个数字往左或者往右作为最慢,然后考虑其他蚂蚁有多少种走路方向。
(1),走的距离大于m/2
假如红色描述的是一个蚂蚁的移动轨迹,那么蓝色部分左边的蚂蚁只能向左走,蓝色右边的蚂蚁只能向右走。
而蓝色部分中的蚂蚁可以向左也可以向右,方案数为2^n,n为蓝色部分蚂蚁数量。
(2),走的距离小于m/2
如图,则蓝色部分左边的蚂蚁只能向左,蓝色部分右边的蚂蚁只能向右。而蓝色部分中间不能有蚂蚁!,这个方案数只能为1
(一开始很2B,打了nlogn的二分找位置,考完试才发现只有60分,其实应该利用A,B数组的单调性O(N)做的。
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 using namespace std; 7 typedef long long ll; 8 const int maxn=5000000,Mod=1e9+7,p=137; 9 int n,ans,bin[maxn+5],x,a,b,c; 10 ll m,A[maxn+5],B[maxn+5],C[maxn+5]; 11 inline int myrand(){ 12 x=(1ll*a*x+b)%c; 13 return x; 14 } 15 inline void Init(){ 16 cin>>n>>x>>a>>b>>c; 17 for(int i=1;i<=(n+1)/2;i++)B[i]=B[i-1]+myrand()+5; 18 m=B[(n+1)/2]<<1|1; 19 for(int i=1;i<=n-(n+1)/2;i++)C[i]=m-(myrand()%(B[i]-B[i-1]-1)+B[i-1]+1); 20 reverse(C+1,C+(n-(n+1)/2)+1); 21 for(int i=1;i<=(n+1)/2;i++)A[i]=B[i]; 22 for(int i=1;i<=n-(n+1)/2;i++)A[i+(n+1)/2]=C[i]; 23 for(int i=1;i<=n;i++) B[i]=m-A[i]; 24 } 25 void updata(int i,int j){ 26 if (i-j>=0) ans=(ans+(std::max(A[i],B[j])%Mod)*bin[i-j]%Mod)%Mod; 27 if (j==i+1) ans=(ans+std::max(A[i],B[j]))%Mod; 28 } 29 void solve(){ 30 bin[0]=1;for (int i=1;i<=n;i++) bin[i]=(bin[i-1]*2)%Mod; 31 int i=1,j=n; 32 while (i<n||j>1){ 33 if (i<n){ 34 if (j==1||A[i+1]<B[j-1]) i++; 35 else j--; 36 }else j--; 37 updata(i,j); 38 } 39 printf("%d ",ans); 40 } 41 int main(){ 42 Init(); 43 solve(); 44 }