问题 H: 嚎叫响彻在贪婪的厂房

问题 H: 嚎叫响彻在贪婪的厂房

时间限制: 1 Sec 内存限制: 128 MB

题目描述
RX:把机器人Hobo,带往改造工厂。
来到了改造工厂,Hobo感到阵阵迷茫,不知道自己将会何去何从。
“当我从这里离开的时候,我还会是Eddie的朋友吗?”
RX:珍娜女王,可以开始了。
铁斯塔:珍娜女王,等到把Hobo改造完了,你父亲的遗愿就能实现了。

机器人的哀嚎传遍了整座工厂,于是,Hobo决定带着他们一起逃离这里。工厂的传送带上依次排列着N个机器人,其中,第i个机器人的质量为Ai。Hobo经过仔细观察,发现:
1.来自同一个家族的机器人,在这N个机器人中一定是连续的一段。
2.如果从第i个机器人到第j个机器人都来自同一个家族,那么Ai到Aj从小到大排序后一定是公差大于1的等差数列的子序列。
Hobo发现,不同家族的个数越少,机器人就会越团结,成功逃离工厂的概率就会越高。Hobo想知道,这N个机器人最少来自几个不同的家族呢?
输入
第一行一个正整数N。
接下来一行N个正整数,第i个正整数为Ai。
输出
一行一个正整数,表示答案。
样例输入 Copy
【样例1】
7
1 5 11 2 6 4 7
【样例2】
8
4 2 6 8 5 3 1 7
样例输出 Copy
【样例1】
3
【样例2】
2
提示
样例1解释
1 5 11 是等差数列{1,3,5,7,9,11}的子序列,
2 4 6 是等差数列{2,4,6,8}的子序列,
7 是等差数列{7,9,11}的子序列。
样例2解释
2 4 6 8 是等差数列{2,4,6,8}的子序列,
1 3 5 7 是等差数列{1,3,5,7}的子序列。
【数据范围】
20% 的数据满足, N ≤ 10 。 N ≤ 10 。 N10
40% 的数据满足, N ≤ 100 。 N ≤ 100 。 N100
60% 的数据满足, N ≤ 1000 , 1 ≤ A i ≤ 1 0 6 。 N ≤ 1000 , 1 ≤ Ai ≤ 10^6 。 N10001Ai106
另有 20% 的数据满足, Ai 互不相同。
100% 的数据满足, N ≤ 100000 , 1 ≤ A i ≤ 1 0 9 。 N ≤ 100000 , 1 ≤ Ai ≤ 10^9 。 N1000001Ai109
题意:
给出你 n n n个机器人的质量 a i a_i ai
他们有两点要求:

  1. 同厂的机器人连续出现
  2. 同厂的机器人排序完,符合等差数列的性质,且公差大于1
    问你这个 n n n个机器人最少的出自几个厂家(家族)?

思路
先说下满足等差数列的性质 ( 2 , 4 , 8 , 12 ) (2 ,4 ,8, 12) (24812)这样也是满足的他们是公差是 2 2 的等差数列的一段。其实看样例解释就能看出来。

公 差 大 于 1 公差大于1 1换种理解方式假设 a , b , c a,b,c a,b,c 公差大于1我们就可以这样理解
x = a b s ( a − b ) x=abs(a-b) x=abs(ab)
y = a b s ( c − b ) y=abs(c-b) y=abs(cb)
因为公差大于 1 1 1所以 g c d ( x , y ) > 1 gcd(x,y)>1 gcd(x,y)>1。如果还是理解不了的话往下看。理解也要往下看。
换种解释:假设公差为 d 且 ( d > 1 ) d且(d>1) d(d>1)那么设 a a 是首项,然后 x x x是差那么 ( d ∣ x ) (d|x) (dx) , x x x整除 d d d. 同理 ( d ∣ y ) (d|y) (dy), y y y整除 d d d,所以差的 g c d gcd gcd大于1就满足条件。

上面这个推推就出来了
看细节:如果两个相同的数连着那么他就一定不行,差就是零,直接退出,新增厂家。
(这些其实最后用的mp就解决了,之所以列出来只是,方便理解,跟fw思路走)然后差为 1 1 1也是不行的, g c d gcd gcd会成为1也该新增厂家。
如果满足 g c d > 1 gcd>1 gcd>1那么直接把这个机器人加到这个厂里,那么就把新的 g c d gcd gcd当成比较对象。
这样你会过50.i am sorry
其实少考虑情况了就是 当 g c d ( ) gcd() gcd()满足是他一样的不能出自一个厂家不论他是否连着。所以我们用mp标记一下就可以了。

注意mp标记

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2e5+7;
#define pii pair<ll,ll>
const int mod=1e9+7;
ll qpow(ll a,ll b) {
    ll sum=1;
    while(b) {
        if(b&1)sum=sum*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return sum;
}
ll a[maxn],d[maxn];
ll gcd(ll a,ll b) {
    while(b) {
        ll tmp=a%b;
        a=b;
        b=tmp;
    }
    return a;
}
map<ll ,ll >mp;
int main() {
    ll n,m;
    cin>>n;
    for(int i=1; i<=n; i++) scanf("%lld",&a[i]);
    ll sum=1,p;
    p=abs(a[2]-a[1]);
    ///mp[a[2]]=1;
    mp[a[1]]=1;
    for(int i=2; i<=n; i++) {
        if(mp[a[i]]==1){
            mp.clear();
            mp[a[i]]=1;
            sum++;
            p=abs(a[i+1]-a[i]);
            continue;
        }
        if(p==0||p==1){
            mp.clear();
            mp[a[i]]=1;
            p=abs(a[i+1]-a[i]);
            sum++;
            continue;
        }
        ll q=abs(a[i]-a[i-1]);
        if(q==0||q == 1) {
            mp.clear();
            mp[a[i]]=1;
            p=abs(a[i+1]-a[i]);
            sum++;
            continue;
        }
 
        if(gcd(q,p)==1) {
            mp.clear();
            mp[a[i]]=1;
            p=abs(a[i+1]-a[i]);
            sum++;
        } else {
            p=gcd(q,p);
            mp[a[i]]=1;
        }
    }
    cout<<sum<<endl;
    return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值