NOI十连测 第四测 T1

 

思路:首先每个蚂蚁移速相同,而且碰到就转头,这其实等价于擦肩而过!

看到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 }
原文地址:https://www.cnblogs.com/qzqzgfy/p/5598622.html