这次考崩了,本来以为可以T1骗点分,看了题面后想了二分,心想40分稳了,然后就干后面的题,最后爆了十分
long long没加,二分时相乘数太大,本以为能骗分。。。。。
这题首先就不讲了,
正解其实不难首先要质因数分解,
因为选出的一段是一个等比序列的子序列,我们分为两种情况:
1. q=1,相当于找一个最长每个数都相等的子串,这个扫一遍就行了。
2. q!=1,那么这个序列最长只有 logn,那么我们可以枚举开头,不妨设开始的两个数为 a[i]和 a[i+1],
其中比较大的一个为 x,另一个 y。
(1) 首先要满足 x%y=0
(2) 让 z=x/y,然后把 z 质因数分解,z=p1^q1*p2^q2*p3^q3......,设 g=gcd(q1,q2,q3...),那么当前序
列的最小公比就是 p1^(q1/g)*p2^(q2/h)*......
(3) 我们找到最小公比后,每当往后加一个数,判断它与前边的数的比是否是最小公比的整次幂,
不是的话就说明不能再加了。
(4) 还有一个要求就是这个序列里不能有重复的数,这个东西用 set 判断就行了。
然后用辗转相除法处理出kx_1,kx_2的比是否为base的整数幂
一开始把辗转相除忘了。。。
质因数分解板子:(将每个数的因子及幂放起来,注意处理质数)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 void work_zhi(ll x) 2 { 3 ll kx=x; 4 for(ll kkk=2;kkk<=min1(sqrt(kx),1000);++kkk) 5 { 6 if((kx%kkk)==0) 7 { 8 th.ps(kkk); 9 ll sum=0; 10 while((kx%kkk)==0) 11 { 12 sum++; 13 kx/=kkk; 14 } 15 c.ps(sum); 16 } 17 } 18 if(kx>1){ 19 th.ps(kx);c.ps(1); 20 } 21 return ; 22 }
AC代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 #include<vector> 7 #include<cmath> 8 #include<bits/stdc++.h> 9 #include<stack> 10 #include<queue> 11 #include<set> 12 #define MAXN 1000001 13 #define ps push_back 14 #define pt printf("-------- "); 15 #define ll long long 16 using namespace std; 17 vector<ll>th,c; 18 ll n,a[MAXN]; 19 ll min1(ll x,ll y){ 20 if(x<y)return x;else return y; 21 } 22 23 void work_zhi(ll x) 24 { 25 ll kx=x; 26 for(ll kkk=2;kkk<=min1(sqrt(kx),1000);++kkk) 27 { 28 if((kx%kkk)==0) 29 { 30 th.ps(kkk); 31 ll sum=0; 32 while((kx%kkk)==0) 33 { 34 sum++; 35 kx/=kkk; 36 } 37 c.ps(sum); 38 } 39 } 40 if(kx>1){ 41 th.ps(kx);c.ps(1); 42 } 43 return ; 44 } 45 bool judge(ll x,ll y,ll p){ 46 // printf("jude%lld %lld ",x,y); 47 /*if(x<y)swap(x,y); 48 ll zheng=1; 49 ll yuan=x; 50 while(x>=y&&(ll)y!=1){ 51 x=x/y; 52 zheng*=y; 53 } 54 x=1;zheng*=y; 55 printf("jj x=%lld y%lld ",x,y); 56 if(zheng*x==yuan)return 1; 57 else return 0;*/ 58 // printf("y=%lld x=%lld ",y,x); 59 while(y<x){y*=p;} 60 if(x==y)return 1; 61 else return 0; 62 } 63 set<ll>kxx; 64 bool judge1(ll x,ll y){ 65 66 if(x<y)swap(x,y); 67 ll q=x/y; 68 if(y*q==x)return 1; 69 else return 0; 70 } 71 ll gcd(ll a,ll b){return (b==0)?a:(gcd(b,a%b));} 72 int main() 73 { 74 //freopen("kx.in","r",stdin); 75 // freopen("kx.out","w",stdout); 76 scanf("%lld",&n); 77 for(ll i=1;i<=n;++i){ 78 scanf("%lld",&a[i]); 79 } 80 ll maxn=1,sum=1; 81 for(ll i=2;i<=n;++i){ 82 83 if(a[i]==a[i-1]){ 84 sum++;maxn=max(maxn,sum); 85 } 86 else{ 87 sum=1; 88 } 89 } 90 // printf("maxn=%lld ",maxn); 91 ll ans=0; 92 for(ll i=2;i<=n;++i) 93 { 94 kxx.clear(); 95 ans=1; 96 ll x_1=i,x_2=i-1; 97 ll kx_1=a[i],kx_2=a[i-1]; 98 if(kx_1<kx_2){ 99 swap(kx_1,kx_2);swap(x_1,x_2); 100 } 101 ll zz=kx_1/kx_2; 102 // printf("kx_1=%lld kx_2=%lld ",kx_1,kx_2); 103 if(!judge1(kx_1,kx_2))continue; 104 if(zz==1)continue; 105 work_zhi(zz);ll gcdd=c[0]; 106 for(ll i=1;i<c.size();++i){ 107 ll kkk=c[i]; 108 gcdd=gcd(gcdd,kkk); 109 } 110 // printf("gcdd=%lld kx_1=%lld kx_2=%lld ",gcdd,kx_1,kx_2); 111 kxx.insert(a[i]);kxx.insert(a[i-1]); 112 ans=2;maxn=max(maxn,ans); 113 ll base=1; 114 for(ll k=0;k<c.size();++k){ 115 for(ll j=1;j<=c[k]/gcdd;++j){ 116 base*=th[k]; 117 } 118 } 119 // printf("base=%lld ",base); 120 c.clear();th.clear(); 121 for(ll j=i+1;j<=n;++j) 122 { 123 if(kxx.count(a[j])!=0){break;} 124 else kxx.insert(a[j]); 125 // printf("----------%lld ",*kxx.find(a[j])); 126 ll to2=a[j]; 127 // printf("a[%lld]=%lld ",j,a[j]); 128 if(kx_2>to2){ 129 swap(kx_2,to2); 130 } 131 // printf("to/kx_2%lld base%lld ",to2/kx_2,base); 132 if(judge(to2,kx_2,base)==1){ 133 ans++;maxn=max(ans,maxn);//printf("ans=%lld maxn=%lld ",ans,maxn); 134 } 135 else { 136 break; 137 } 138 } 139 kxx.clear(); 140 } 141 printf("%lld ",maxn); 142 }
************************************************************
set中常用的方法
begin() ,返回set容器的第一个元素
end() ,返回set容器的最后一个元素
clear() ,删除set容器中的所有的元素
empty() ,判断set容器是否为空
max_size() ,返回set容器可能包含的元素最大个数
size() ,返回当前set容器中的元素个数
rbegin ,返回的值和end()相同
rend() ,返回的值和rbegin()相同