2015暑假多校联合---Problem Killer(暴力)

原题链接

Problem Description
You are a "Problem Killer", you want to solve many problems. 
Now you have n problems, the i-th problem's difficulty is represented by an integer ai (1ai109).
For some strange reason, you must choose some integer l and r (1lrn), and solve the problems between the l-th and the r-th, and these problems' difficulties must form an AP (Arithmetic Progression) or a GP (Geometric Progression). 
So how many problems can you solve at most?

You can find the definitions of AP and GP by the following links:
https://en.wikipedia.org/wiki/Arithmetic_progression
https://en.wikipedia.org/wiki/Geometric_progression
 
Input
The first line contains a single integer T, indicating the number of cases. 
For each test case, the first line contains a single integer n, the second line contains n integers a1,a2,,an

T104,n106
 
Output
For each test case, output one line with a single integer, representing the answer.
 
Sample Input
2
5
1 2 3 4 6
10
1 1 1 1 1 1 2 3 4 5
 
Sample Output
4
6

 题意:输入n个数,求其中最长的区间的长度(区间满足等差数列或者等比数列);

 思路:两重循环暴力从每个数开始找,但是这样会超时,可以优化一下,记录从当前数开始的等差数列最远的位置,下次从上次记录的最远的位置开始找,这样复杂度会下降很多;

         我发现了一个很有意思的事情,我开始写的程序超时了,后来我删掉了一些东西AC了,但我感觉有bug,于是我想了组数据n=5  5个数4 ,8 ,12 , 18 , 27   后面4个数满足等比数列,最长区间应该是4,而我的程序输出是3,  同样这组数据n=6  6个数8 ,16 ,24 , 36 , 54 , 81  后面5个数满足等比数列,输出应该是5,而我的程序输出是4。  我想了一下每次从上次记录的最远的位置开始找,有可能记录的位置的前一位也满足等比数列,所以在计算等比数列长度时得计算一下前一位是否满足;

开始的代码如下:

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <cstring>
using namespace std;
long long a[1000005];

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%lld",&a[i]);
        int tmp=0;
        int t,j;
        for(int i=0;i<n;i=t)
        {
            for(j=i+1;j<n;j++)
            {
                if(a[j]!=a[i]+(a[i+1]-a[i])*(j-i))
                  break;
            }
            t=j-1;
            tmp=max(tmp,j-i);

            for(j=i+1;j<n;j++)
            {
                if(a[j-1]*a[i+1]%a[i]==0&&a[j]==a[j-1]*a[i+1]/a[i])
                   continue;
                else break;
            }
            tmp=max(tmp,j-i);
            //cout<<"t: "<<t<<endl;
            //if(j-1>i)
            //t=min(t,j-1);
            if(t==n-1)break;
        }
        printf("%d
",tmp);
    }
    return 0;
}

后来修改过的代码:

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <cstring>
using namespace std;
long long a[1000005];

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%lld",&a[i]);
        int tmp=0;
        int t,j;
        for(int i=0;i<n;i=t)
        {
            for(j=i+1;j<n;j++)
            {
                if(a[j]!=a[i]+(a[i+1]-a[i])*(j-i))
                  break;
            }
            t=j-1;
            tmp=max(tmp,j-i);

            for(j=i+1;j<n;j++)
            {
                if(a[j-1]*a[i+1]%a[i]==0&&a[j]==a[j-1]*a[i+1]/a[i])
                   continue;
                else break;
            }
            int f=0;
            if(a[i-1]*a[i+1]%a[i]==0&&a[i]==a[i-1]*a[i+1]/a[i])
                f=1;
            tmp=max(tmp,j-i+f);

            if(t==n-1)break;
        }
        printf("%d
",tmp);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/chen9510/p/5806769.html