Codeforces Round #694 (Div. 2)_B. Strange List(规律)

39 篇文章 1 订阅
10 篇文章 0 订阅

链接https://codeforces.com/problemset/problem/1471/B

题目
You have given an array a of length n and an integer x to a brand new robot. What the robot does is the following: it iterates over the elements of the array, let the current element be q. If q is divisible by x, the robot adds x copies of the integer qx to the end of the array, and moves on to the next element. Note that the newly added elements could be processed by the robot later. Otherwise, if q is not divisible by x, the robot shuts down.

Please determine the sum of all values of the array at the end of the process.

题意
对于每个样例首先给出数字n和x,n代表序列长度。
接下来给出n个数字,从第一个元素开始操作。
每次操作规则如下:

  • 1.如果当前元素z可以整除x,则在序列后插入x个(z/x);
  • 2.如果当前元素z无法整除x,则结束操作;

输出操作之后得到的序列中所有数字之和
(结合样例理解)

思路
一开始想着设置两个队列,一个队列存新增添的数,另一个队列存操作完的数。
(比如12被操作完成后会被放到2号队列,而它产生的数(假如是两个6),则会被放到1队列)

操作前:

队列1队列2
12

操作后:

队列1队列2
6,612

然后将两个队列所有元素的值求和就ok,但是在测试点5的地方超了内存。
所以说这个题其实是一个规律题。

我们看接下来这个(默认x=2):

12

序列中12整除2,得到两个6,,序列和增加了12。
我们发现,序列在增加数字的时候,对于序列和来说,只是增加了一个a[i]。
而12能够整除2两次(12->6->3),所以最后答案就是12*(2+1)=36。

这还不足以发现问题,我们再来一个:

12  4

12可以整除2两次(12->6->3),4也可以整除2两次。
所以最后答案就是12*(2+1)+4*(2+1)=48。

还不足以发现问题?看最后一个:

16  2  4 

16可以整除4次x,2只能整除x1次,4能够整除x2次。

  1. 16 2 4 8 8
  2. 16 2 4 8 8 1 1
  3. 16 2 4 8 8 1 1 2 2
  4. 16 2 4 8 8 1 1 2 2 4 4
  5. 16 2 4 8 8 1 1 2 2 4 4 4 4

然后我们就发现:16只能用2次,4只能用1次,而2是阻断操作的原因。

关键就来了,我们找到序列中能够对x整除次数cnt最少的那个位置,那么在它之前的数最多也只能操作cnt+1次,在它之后(包含本身)的数最多只能操作cnt次。

上代码,伊丽莎白!

在这里插入图片描述
代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<stack>
#define inf 0x3f3f3f
using namespace std;
const int maxn=2e5+100;
typedef long long ll;

ll a[maxn];
int main()
{
    ll t,x,n;
    cin>>t;
    while(t--)
    {
        cin>>n>>x;
        ll sum=0;
        ll pos=0,cnt=inf;
        for(int i=0;i<n;i++)
        {
            ll s=0;
            cin>>a[i];
            for(ll j=x;;j*=x)  //检测当前数字能够整除x几次,可优化(替代)
            {
                if(a[i]%j==0)
                    s++;
                else
                    break;
            }
            if(s<cnt)
            {
                pos=i;
                cnt=s;
            }
        }
        for(int i=0;i<pos;i++)
            sum+=(cnt+2)*a[i];
        for(int i=pos;i<n;i++)
            sum+=(cnt+1)*a[i];
        cout<<sum<<endl;
    }
}

我已经1000%了!

在这里插入图片描述

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值