PAT.1096 Consecutive Factors

PAT.1096 Consecutive Factors

题目链接

看题干的意思是给出一个数n,要你寻找在所有可能的因数分解序列上上最长的连续因数子序列,输出这个长度并输出最小的子序列。

说实话这个最小我一开始没怎么看明白,因为如果说最小是左界最小,那明显样例的输出应该是1*2*3而不是5*6*7,但如果说这个最小指的是size最小,那输出应该是3,也不是5*6*7,于是我陷入了疑惑…

首先想到的做法是在1-N的范围上做滑动窗口,还就那个处理连续子序列相关问题的经典思路,先是按照左界最小的做法提交了一次(当然不可能是对的,因为样例都过不了)。

一些尝试

在左界最小没能通过的情况下,在左界最小的基础上不考虑因数分解中包含1的情况,即从2开始做滑动窗口,拿到了15/20,最后一个测试点超时(想想也是,毕竟1e9的数据摆在那里)。

那么看来题干的最小很可能是最小左界,同时不包含1的情况。

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;

ll n,l = 2,r = 2,maxSize = 0;
deque<ll> res;
deque<ll> window;

int main(){
    cin>>n;
    while(r <= n){
        if(n % r == 0){
            window.push_back(r);
            if(r - l + 1 > maxSize){
                maxSize = r - l + 1;
                res = window;
            }
            r++;
        }else{
            if(!window.empty()) window.pop_front();
            l++;
            r = max(l,r);
        }
    }
    cout<<maxSize<<endl;
    while(!res.empty()){
        cout<<res.front();
        res.pop_front();
        if(res.size() > 0) cout<<"*";
    }
}

题解

还就那个恶堕然后使用枚举。

首先考虑枚举什么,因为连乘增长很快,只要大概十几连乘就能超过1e9,所以我们可以考虑枚举子序列的长度。同时显然,只要两个大于sqrt(n)的数相乘就会大于n,所以我们枚举子序列中的数的时候只需要考虑小于sqrt(n)的数(这里有一点需要注意,就是序列刚好跨过开根的情况,比如6=2*3,所以实际上我们应该枚举的范围是2 ~ sqrt(n) + 1

理清思路后我们只要从枚举左界的同时枚举子序列的长度即可,对于PAT的数据,考虑到开根的情况,子序列长度枚举到6、7就能过全部测试点了。

特别需要注意的是

  • 这个方法对质数无可奈何,当n为质数时会得到最大子序列长度为0,所以我们需要进行特判,在这种情况下直接输出1\nN
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;

ll n,carry;
int r,maxSize;
vector<int> window;
vector<int> res;

int main(){
    cin>>n;
    r = sqrt(n) + 1;
    for(int i = 2 ; i <= r ; ++i){
        carry = 1;
        window.clear();
        for(int len = 1 ; len <= 6 ; ++len){
            carry *= i + len - 1;
            if(n % carry == 0){
                window.push_back(i + len - 1);
                if(window.size() > maxSize){
                    maxSize = window.size();
                    res = window;
                }
            }else break;
        }
    }
    if(maxSize == 0) cout<<1<<endl<<n;
    else{
        cout<<maxSize<<endl;
        for(int i = 0 ; i < maxSize ; ++i){
            cout<<res[i];
            if(i != maxSize - 1) cout<<"*";
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值