题目链接:https://www.cnblogs.com/Juve/articles/11186805.html(密码是我的一个oj用户名)

题解:

这题我考试打的暴力,只有5分。

一开始理解错题意了,以为2,4,32这类不符合,于是有了下面的代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define MAXN 100005
#define re register
#define in inline
using namespace std;
in ll read(){
re ll x=;char ch=getchar();
while(ch<''||ch>''){ch=getchar();}
while(ch>=''&&ch<=''){
x=(x<<)+(x<<)+ch-'';
ch=getchar();
}
return x;
}
ll n,a[MAXN],tot=,ans=;
in ll max(re ll a,re ll b){
return a>b?a:b;
}
in ll min(re ll a,re ll b){
return a<b?a:b;
}
in bool judge(re ll x,re ll y){
re ll num=,q;
re ll b[MAXN];
for(re ll i=x;i<=y;i++){
b[++num]=a[i];
}
sort(b+,b+num+);
//cout<<b[1]<<' '<<b[2]<<endl;
//if(b[2]==b[1]) return 0;
q=b[]/b[];
for(re ll i=;i<=num;i++){
if(b[i]%b[i-]!=) return ;
if(b[i]==b[i-]) return ;
if(b[i]/b[i-]!=q) return ;
}
return ;
}
signed main(){
//freopen("test.in","r",stdin);
n=read();
for(re ll i=;i<=n;i++){
a[i]=read();
if(a[i]==) ans=;
if(a[i]==a[i-]) tot++;
else{
ans=max(tot,ans);
tot=;
}
}
if(ans==n){
printf("%lld\n",ans);
return ;
}
for(re ll i=;i<=n;i++){
if(!a[i]||!a[i+]){
continue;
}
for(re ll j=i+;j<=n;j++){
//cout<<j<<endl;
if(judge(i,j)){
//cout<<i<<' '<<j<<endl;
tot=j-i+;
ans=max(ans,tot);
//cout<<tot<<endl;
}
else{
ans=max(ans,tot);
}
}
}
ans=max(ans,tot);
printf("%lld\n",ans);
return ;
}

5分

考完试看正解,没看懂,于是开始更改我的暴力思路

设dp[q][i]表示公比为q,以i结尾能组成题目中序列的个数

我们先求出数列的max和min,得到q的范围

首先枚举q,之后枚举整个数列,对与每个a[i]和a[i-1],如果max(a[i],a[i-1])%min(a[i],a[i-1]),

那么枚举q的指数qp,如果min(a[i],a[i-1])*qp=max(a[i],a[i-1]),那么从i向前dp[q][i-1]中判重,若没有重复,那么dp[q][i]=dp[q][i-1]+1;

判重是防止以下情况:4,2,4;

4在前面出现过一次了,所以dp[q][3]=2而不是3;

具体做法:

for(ll p=;p<=;p++){
ll Q=power(q,p);
if(Q>maxx) break;
if(mi*Q==ma){
bool flag=;
for(ll k=;k<=dp[q][i-];k++){
if(a[i]==a[i-k]){
dp[q][i]=k;flag=;
ans=max(ans,dp[q][i]);
//cout<<ans<<' '<<dp[q][i]<<' '<<q<<' '<<i<<endl;
break;
}
}
if(!flag){
dp[q][i]=dp[q][i-]+;
ans=max(ans,dp[q][i]);
//cout<<ans<<' '<<dp[q][i]<<' '<<q<<' '<<i<<endl;
}
break;
}
}

细节的地方包括判断0以及公比是一的情况,随时更新ans

Ps:因为这道题的数据实在是不好造,所以最后公比最大不会很大,博主试验过了,公比最大是10

于是我们快乐地A掉了这道题

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define MAXN 100005
#define re register
#define in inline
using namespace std;
in ll read(){
re ll x=;char ch=getchar();
while(ch<''||ch>''){ch=getchar();}
while(ch>=''&&ch<=''){
x=(x<<)+(x<<)+ch-'';
ch=getchar();
}
return x;
}
ll n,a[MAXN],tot=,ans=,maxx=,minn=9e18;
ll max_q,dp[][MAXN];//dp[q][i]表示公比为q,以一下标i结尾的序列最大能得到多长的等比序列
in ll max(re ll a,re ll b){
return a>b?a:b;
}
in ll min(re ll a,re ll b){
return a<b?a:b;
}
ll power(ll a,ll b){
ll ans=;
for(;b;b>>=){
if(b&) ans=(ll)ans*a;
a=(ll)a*a;
}
return ans;
}
signed main(){
n=read();
//cout<<n<<endl;
for(re ll i=;i<=n;i++){
a[i]=read();
maxx=max(a[i],maxx);
minn=min(a[i],minn);
if(a[i]==){
ans=max(ans,tot);
tot=;
continue;
}
if(a[i]==a[i-]){
tot++;
ans=max(ans,tot);
}
else{
ans=max(ans,tot);
tot=;
}
//cout<<tot<<endl;
}
// cout<<ans<<endl;
if(minn==) minn=;
max_q=min(,maxx/minn);
//cout<<max_q<<endl;
for(ll q=;q<=max_q;q++){//枚举公比
dp[q][]=;
if(a[]==) dp[q][]=;
else dp[q][]=;
for(ll i=;i<=n;i++){
if(a[i]==){
dp[q][i]=;
continue;
}
ll ma=max(a[i],a[i-]),mi=min(a[i],a[i-]);
//cout<<i<<endl;
//cout<<ma<<' '<<mi<<endl;
if(ma==mi){
dp[q][i]=;
continue;
}
if(mi==||ma%mi!=){
dp[q][i]=;
//cout<<ans<<' '<<dp[q][i]<<' '<<q<<' '<<i<<endl;
}else{
for(ll p=;p<=;p++){
ll Q=power(q,p);
if(Q>maxx) break;
if(mi*Q==ma){
bool flag=;
for(ll k=;k<=dp[q][i-];k++){
if(a[i]==a[i-k]){
dp[q][i]=k;flag=;
ans=max(ans,dp[q][i]);
//cout<<ans<<' '<<dp[q][i]<<' '<<q<<' '<<i<<endl;
break;
}
}
if(!flag){
dp[q][i]=dp[q][i-]+;
ans=max(ans,dp[q][i]);
//cout<<ans<<' '<<dp[q][i]<<' '<<q<<' '<<i<<endl;
}
break;
}
}
}
}
}
//for(ll i=1;i<=max_q;i++)
// for(ll j=1;j<=n;j++)
// cout<<dp[i][j]<<' '<<i<<' '<<j<<endl;
printf("%lld\n",ans);
return ;
}

但其实这还不是正解

正解非常神仙:

因为选出的一段是一个等比序列的子序列,我们分为两种情况:
1. q=1,相当于找一个最长每个数都相等的子串,这个扫一遍就行了。
2. q!=1,那么这个序列最长只有$log_{2}n$,那么我们可以枚举开头,不妨设开始的两个数为 a[i]和 a[i+1],
其中比较大的一个为 x,另一个 y。
(1) 首先要满足 x%y=0
(2) 让 z=$\frac{x}{y}$,然后把 z 质因数分解,z=$p_{1}^{q_2}$×$p_{1}^{q_2}$×$p_{1}^{q_2}$......,设 g=gcd(q1,q2,q3...),那么当前序
列的最小公比就是 $p_{1}^{\frac{q_{1}}{g}}$×$p_{2}^{\frac{q_{2}}{h}}$×......
(3) 我们找到最小公比后,每当往后加一个数,判断它与前边的数的比是否是最小公比的整次幂,
不是的话就说明不能再加了。
(4) 还有一个要求就是这个序列里不能有重复的数,这个东西用 set 判断就行了。
复杂度 O($nlog_{2}^{2}n$);

正解代码:

 #include<bits/stdc++.h>
using namespace std;
const long long L=<<|;
char buffer[L],*S,*TT;
#define getchar() ((S==TT&&(TT=(S=buffer)+fread(buffer,1,L,stdin),S==TT))?EOF:*S++)
long long n;
long long data[],ans=,z[],q[],tot=;
long long p[],c[];
set<long long> s;
inline long long read()
{
register long long a=,b=;char ch=getchar();
while(ch<''||ch>'')b=(ch=='-')?-:,ch=getchar();
while(ch>=''&&ch<='')a=(a<<)+(a<<)+(ch^),ch=getchar();
return a*b;
}
inline long long qpow(register long long x,register long long y)
{
register long long ans=;
while(y)
{
if(y&)ans*=x;
x*=x;
y>>=;
}
return ans;
}
inline long long gcd(register long long x,register long long y)
{
register long long i,j;
if(x==)return y;
if(y==)return x;
for(i=;==(x&);++i)x>>=;
for(j=;==(y&);++j)y>>=;
if(j<i)i=j;
while()
{
if(x<y)x^=y,y^=x,x^=y;
if(==(x-=y))return y<<i;
while(==(x&))x>>=;
}
}
inline void divide(register long long x)
{
tot=;
for(register long long i=;i<=min((long long),(long long)sqrt(x));i++)
if(!(x%i))
{
p[++tot]=i;c[tot]=;
while(!(x%i))x/=i,c[tot]++;
}
if(x>)p[++tot]=x,c[tot]=;
}
inline bool jud(register long long x,register long long y,register long long q)
{
if(x%y)return ;
x/=y;
while(x%q==)x/=q;
if(x!=)return ;
return ;
}
signed main()
{
n=read();
register long long sum=;
for(register long long i=;i<=n;++i)q[i]=;
for(register long long i=;i<=n;++i)
{
data[i]=read();
if(data[i]==data[i-])++sum;
else sum=;
ans=max(ans,sum);
if(i>=)
{
register long long x=max(data[i],data[i-]);
register long long y=min(data[i],data[i-]);
if(x%y)continue;
register long long d=x/y;
divide(d);
register long long g=c[];
for(register long long m=;m<=tot;++m)
{
if(g==)break;
g=gcd(g,c[m]);
}
for(register long long l=;l<=tot;++l)
{
q[i-]*=qpow(p[l],c[l]/g);
if(q[i-]>)
{
q[i-]=;
break;
}
}
}
}
for(register long long i=;i<=n;i++)
if(q[i-])
{
if(q[i-]==)continue;
s.clear();
s.insert(data[i-]),s.insert(data[i]);
for(register long long j=i+;j<=n;j++)
{
if(s.count(data[j]))break;
register long long x=max(*--s.end(),data[j]);
register long long y=min(*--s.end(),data[j]);
if(jud(x,y,q[i-]))s.insert(data[j]);
else break;
}
register long long mm=s.size();
ans=max(ans,mm);
}
printf("%lld",ans);
}

非常感谢soul提供的代码,soul有素质有情怀有状态有节操%拜

HZOI2019序列的更多相关文章

  1. 【夯实PHP基础】UML序列图总结

    原文地址 序列图主要用于展示对象之间交互的顺序. 序列图将交互关系表示为一个二维图.纵向是时间轴,时间沿竖线向下延伸.横向轴代表了在协作中各独立对象的类元角色.类元角色用生命线表示.当对象存在时,角色 ...

  2. Windows10-UWP中设备序列显示不同XAML的三种方式[3]

    阅读目录: 概述 DeviceFamily-Type文件夹 DeviceFamily-Type扩展 InitializeComponent重载 结论 概述 Windows10-UWP(Universa ...

  3. 软件工程里的UML序列图的概念和总结

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习! 软件工程的一般开发过程:愿景分析.业务建模,需求分析,健壮性设计,关键设计,最终设计,实现…… 时序图也叫序列图(交互图),属于软件 ...

  4. python序列,字典备忘

    初识python备忘: 序列:列表,字符串,元组len(d),d[id],del d[id],data in d函数:cmp(x,y),len(seq),list(seq)根据字符串创建列表,max( ...

  5. BZOJ 1251: 序列终结者 [splay]

    1251: 序列终结者 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 3778  Solved: 1583[Submit][Status][Discu ...

  6. 最长不下降序列nlogn算法

    显然n方算法在比赛中是没有什么用的(不会这么容易就过的),所以nlogn的算法尤为重要. 分析: 开2个数组,一个a记原数,f[k]表示长度为f的不下降子序列末尾元素的最小值,tot表示当前已知的最长 ...

  7. [LeetCode] Sequence Reconstruction 序列重建

    Check whether the original sequence org can be uniquely reconstructed from the sequences in seqs. Th ...

  8. [LeetCode] Binary Tree Longest Consecutive Sequence 二叉树最长连续序列

    Given a binary tree, find the length of the longest consecutive sequence path. The path refers to an ...

  9. [LeetCode] Repeated DNA Sequences 求重复的DNA序列

    All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACG ...

随机推荐

  1. SpringBatch批处理框架:入门项目

    1.项目结构如下:

  2. VS2010-MFC(常用控件:列表框控件ListBox)

    转自:http://www.jizhuomi.com/software/186.html 列表框控件简介 列表框给出了一个选项清单,允许用户从中进行单项或多项选择,被选中的项会高亮显示.列表框可分为单 ...

  3. service sshd start启动失败,Badly formatted port number.

    在做xhell学习的时候,把端口号修改了,后面忘记修改回 来,导致 [root@MyRoth 桌面]# service sshd start 正在启动 sshd:/etc/ssh/sshd_confi ...

  4. Object 和Throwable

    Object java.lang.Object 所有类的超类 Object里面有的方法所有的类都有 Object方法: String toString() 返回对象的字符串表现形式  类名 + @ + ...

  5. python数据池,python3编码str转bytes,encode

    一.python2 python3的区别 默认编码:2--ASCII码  3---UTF-8 print:python2 可以不需要加括号(),python3必须加括号 python2中有range, ...

  6. CSS三大特性之继承性

    1.并不是所有的属性都可以继承,只有以color/font/text/line开头的属性 才可以继承. 2.在CSS的继承中,不仅仅是儿子可以继承,只要是后代都可以继承. 3.继承中的特殊性 3.1  ...

  7. springcloud ribbon Finchley 版本,自定义算法

    引用上一个项目,在原有的基础上进行更改,添加springcloud的内荣. eureka-server 和上一个springcloud eureka的一样,没有改动. 添加cloud-api pack ...

  8. Python学习之--迭代器、生成器

    迭代器 迭代器是访问集合元素的一种方式.从对象第一个元素开始访问,直到所有的元素被访问结束.迭代器只能往前,不能往后退.迭代器与普通Python对象的区别是迭代器有一个__next__()方法,每次调 ...

  9. iOS逆向系列-脱壳

    概述 通过iOS逆向系列-逆向App中使用class-dump工具导出App的Mach-O文件所有头文件.Hopper工具分析App的Mach-O文件代码大概实现.但是这些前体是App的Mach-O没 ...

  10. 《代码整洁之道》ch5~ch9读书笔记 PB16110698(~3.15) 第二周

    <代码整洁之道>ch5~ch9读书笔记 本周我阅读了本书的第5~9章节,进一步了解整洁代码需要注意的几个方面:格式.对象与数据结构.错误处理.边界测试.单元测试和类的规范.以下我将分别记录 ...