计蒜客NOIP2017提高组模拟赛(五)day1-展览

传送门

发现这题选或不选对状态的优劣程度不会产生影响,如果已经确定了两个数a和b,那么最优的首项和公比也都是唯一确定的,

与对于后面的数x,加进去也好不加进去也好,首项和公比依旧是原来的

于是我们用尺取算法,用两个指针来扫一遍,

如果只有一个数且下一个数能被整除,就加进去,然后确定首项和公比

如果只有一个数且下一个数不能整除,两个指针直接指向下一个数

如果有多个数且下一个数满足公式,就加进来

如果有多个数且下一个数不满足公式,两个指针直接指向下一个数

这样对于最优解,一定是可以找到的

顺便说下最优的公比和首项的确定:

已知两个数x y,求满足它们的最优的首项 公比

设x=a*q^k1 y=a*q^k2 且x>y

那么x/y得到q^(k1-k2),

由于最优的公比一定尽可能小,所以要使指数尽可能大,就把q质因数分解,指数取gcd提出

这样就得到了公比,拿这个公比不断地除以一开始的x,就得到了首项

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<map>
  7 #include<set>
  8 #include<queue>
  9 #include<vector>
 10 #define INF 0x7f7f7f7f
 11 #define pii pair<int,int>
 12 #define ll long long
 13 #define MAXN 100005
 14 using namespace std;
 15 
 16 ll read(){
 17     ll x=0,f=1;char ch=getchar();
 18     while(ch<'0'||ch>'9'){if('-'==ch)f=-1;ch=getchar();}
 19     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 20     return x*f;
 21 }
 22 int n;
 23 set<ll> s;
 24 ll a[MAXN];
 25 int gcd(int x,int y){
 26     return (y==0?x:gcd(y,x%y));
 27 }
 28 ll Pow(ll x,ll y){
 29     ll ret=1;
 30     while(y){
 31         if(y&1){
 32             ret*=x;
 33         }
 34         x*=x;
 35         y>>=1;
 36     }
 37     return ret;
 38 }
 39 int gt(ll x,ll y,ll &b,ll &q){
 40     ll t=x/y;
 41     if(1==t){
 42         b=x,q=1;
 43         return 1;
 44     }
 45     vector<pii> vs;
 46     for(int i=2;i<=1000;i++){
 47         if(t%i==0){
 48             int cnt=0;
 49             while(t%i==0){
 50                 cnt++;
 51                 t/=i;
 52             }
 53             vs.push_back(make_pair(i,cnt));
 54         }
 55     }
 56     if(t>1000){
 57         return -1;
 58     }
 59     int g=vs[0].second;
 60     for(int i=1;i<vs.size();i++){
 61         g=gcd(g,vs[i].second);
 62     }
 63     q=1;
 64     for(int i=0;i<vs.size();i++){
 65         q*=Pow((ll)vs[i].first,(ll)vs[i].second/g);
 66     }
 67     b=y;
 68     while(b%q==0){
 69         b/=q;
 70     }
 71     return 1;
 72 }
 73 int check(ll x,ll b,ll q){
 74     if(x%b){
 75         return 0;
 76     }
 77     if(q==1){
 78         return (x==b);
 79     }
 80     if(s.count(x)){
 81         return 0;
 82     }
 83     x/=b;
 84     ll t=q;
 85     int L=0,R=log(1.0*x)/log(1.0*q)+3;
 86     while(R-L>1){
 87         int mid=(L+R)/2;
 88         ll t=Pow(q,(L+R)/2);
 89         if(t>=x){
 90             R=mid;
 91         }
 92         else{
 93             L=mid;
 94         }
 95     }
 96     if(Pow(q,L)==x||Pow(q,R)==x){
 97         return 1;
 98     }
 99     return 0;
100 }
101 int main()
102 {
103 //    freopen("seq2.in","r",stdin);
104 //    freopen("seq.out","w",stdout);
105     n=read();
106     for(int i=1;i<=n;i++){
107         a[i]=read();
108     }
109     int L=1,R=1;
110     int ans=1;
111     ll b=0,q=0;
112     s.insert(a[1]);
113     for(int i=2;i<=n;i++){
114         ll t1=a[R],t2=a[i];
115         if(t1<t2){
116             swap(t1,t2);
117         }
118         if(t1%t2!=0){
119             s.clear();
120             s.insert(a[i]);
121             L=i,R=i;
122             continue;
123         }
124         if(L==R){                
125             R++;
126             s.insert(a[R]);
127             if(-1==gt(t1,t2,b,q)){
128                 L++;
129                 s.clear();
130                 s.insert(a[L]);
131             }
132         }
133         else if(check(a[i],b,q)){
134             R++;
135             if(q!=1)
136                 s.insert(a[R]);
137         }
138         else{
139             s.clear();
140             s.insert(a[i]);
141             L=i,R=i;
142         }
143         ans=max(ans,R-L+1);        
144     } 
145     printf("%d
",ans);
146     return 0;
147 }
原文地址:https://www.cnblogs.com/w-h-h/p/7770671.html