北邮OJ 884. 16校赛-Average Modulo
時間限制 5000 ms 內存限制 65536 KB
題目描述
We define function g on an array as:
Here, p is a given constant, and n is the length of the array.
You are given p and an array A and a length k.
You need to find the maximum value of g over all contiguous subarrays of A that are of length ≥ k.
輸入格式
The first line of input contains T, the number of test cases. Each test case contains two lines. The first line of each test case contains three integers: N, p and k, respectively.
The second line of each test case contains N integers contained in array A.
1≤T≤10
1≤N≤5?104
1≤K≤min(300,N),1≤P≤109
1≤Ai≤109
輸出格式
For each test case, output one line containing two space separated integers: p and q. If the answer is an integer x, then output x and 1 separated by a space.
Otherwise, output p and q if pq is the answer is in its simplest form.
Explanation of example
In the first test case, when length ≥2, the maximum g value is obtained when you take the entire array, so g is 53.
In the second case, all f values are even. Hence, when we take modulo 2, the answer is 0 for any array.
In the third case, p is 1, and the value is 0 for any array.
輸入樣例
3
3 100 2
2 1 2
5 2 1
2 10 4 6 8
5 1 2
100 213142 3123 123 321
輸出樣例
5 3
0 1
0 1
題意為,找出給定序列中的一個滿足長度≥k的連續子序列,使得這個子序列的序列和模上p再除以n盡可能的大。
比如a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,找出其中長度≥2的一段連續子序列,使得他們相加之后mod p = tmp,tmp / n= tmp2,使得tmp2盡可能的大。
乍看之下又是一道枚舉題,但是n的范圍最大是5?104,如果從length=k枚舉到length=n,O(n2)的復雜度明顯就超時了,這時候有兩種思路,第一種思路是自己打表出數據,用O(n2)的枚舉法測一下答案的連續子序列長度最大是多少,
打表代碼如下
#include<bits/stdc++.h> #define K 5 using namespace std; int main(){srand(time(NULL));freopen("tsx.txt","w",stdout);int n=50000,k=200,ts=1000,p=1000000000;printf("%d\n",ts);while(ts--){printf("%d %d %d\n",n,p,k);for(int i=0;i<n;i++)printf("%d%c",rand()%p+1,i==n-1?'\n':' ');}return 0; }然后用裸的O(n2)的枚舉測了幾千組自己生成的樣例,答案長度最大小于k的1.5倍,比賽時穩妥起見開了k的3倍,時間5s綽綽有余。
第二種思路呢,是用數學思想證明,首先(a+b)%p =(a%p + b%p)%p
令a=Σ2ki=0ai,b=Σ2k+xi=2k+1ai
(a+b)%p2k+x=(a%p+b%p)%p2k+x
≤ a%p2k+x+ b%p2k+x
≤max(a%p2k , b%px )
即當枚舉到長度≥2k但≤4k的時候(更長的情況可以遞推),設長度為2k+x,一定可以劃分為一個2k和x長度的兩個連續子序列,它們的值一定可以代替(大于等于)原始2k+x串的值。
解決代碼如下
#include<cstdio> #include<cmath> #include<algorithm> #define MA 50050 using namespace std; int a[MA],sum[MA],n,k,p; int gcd(int a,int b){return b==0?a:gcd(b,a%b);} int main(){int i,j,k,len,t;for(scanf("%d",&t);t--;){scanf("%d%d%d",&n,&p,&k);for(i=1;i<=n;i++)scanf("%d",&a[i]);for(i=1;i<=n;i++)sum[i]=(sum[i-1]+a[i])%p;int up=0,down=1;int lim=k*3;//根據數學驗證,取2k即可for(len=k;len<=lim;len++){for(i=0;i+len<=n;i++){int tmpa=(p+sum[i+len]-sum[i])%p;int tmpb=len;double ta=1.0*up/down;double tb=1.0*tmpa/tmpb;if(ta<tb){up=tmpa;down=tmpb;}}}int gcd_=gcd(up,down);printf("%d %d\n",up/gcd_,down/gcd_);}return 0; }總結
以上是生活随笔為你收集整理的北邮OJ 884. 16校赛-Average Modulo的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于KD树(未完)
- 下一篇: 北邮OJ 980. 16校赛-R_clo