小埋的神秘仰慕者

小埋的神秘仰慕者 ——风速法师

先看题目描述: 小埋从他的一个神秘仰慕者那里得到了一个长度为 n 的整数数组 a1,a2,…,an。小埋认为让数组不递减就能辨认出这位神秘的仰慕者。 小埋可以使用下面的操作使数组不递减:

  • 选择数组 a 中的元素a i 和一个整数 x,使得 1<=x<ai 。两个元素 x 和ai−x 替换 ai,新的元素x和ai−x 将依次放入数组 a 。

  • 更具体的说,假设操作前的数组是 1,2,…,a1,a2,…,ai,…,ak 是数组 a。操作之后,它就等于1,2,…,ai−1,x,ai-x,ai+1,…,an。注意,每次操作后,a 的长度都会增加 1

再看样例:

4

3

1 3 2

4

1 2 3 4

3

3 2 1

7

1 4 4 3 5 7 6

我们一组一组看:

3

1 3 2

把3分成两份 :1和2

变成:1,1,2,2

再来看下一个样例

4

1 2 3 4

无论是拿一个,都不用变

3

3 2 1

先把2 分成两份:1,1

现在是 3,1,1,1(这里注意,是只有两次分割)

再把3分成3分:1 1 1

最后就是1,1,1,1,1,1

欧耶,又水完一段:sweat_smile:

最后也是最难的一段:

7

1 4 4 3 5 7 6

从后往前看,7比6大分成两份足以:3和4

这是为了保持3和4的良好性质,这里保留成3 4 6

接着5比3大,也是平分,2 和3。 现在是2 3 3 4 6

接着3比2大,平分。现在是1 2 2 3 3 4 6

接下来的两个4都是要分成4份,也就是分三次,1 1 1 1 1 1 1 1 1 1 2 3 3 4 6

一共有1+1+1+3+3=9次

这里你发现我一直在讲分成几个几次

但是这里的都是均分,为什么,因为一下三点

  • 不能浪费太多,因为你每填一个数字都是后面的上限,不然下一个是100,但是你这一个是1
  • 不能把小的太小,因为后面的就会要减少很多。不然就可以把1000分成1和999,这样分的次数一定多许多
  • x加大时ai-x一定减少。但是要同时满足的话只有均分时才行。

那么我们从找到x变成找到分成几份。

这里的代码运用了和线性斐波纳吉差不多的思路,核心代码如下:

for(int i = n-1;i >= 1;i--){
	int x = a[i + 1] / c;
	c = ( a[ i ] + x - 1 ) / x;
	c = max( c , 1ll );
	res += c - 1;
}

温馨提示:进度条已过半,请放心食用。

前话:c是上一个分割的份数

我们一条一条来看, for()是为了倒序检查,因为最后一个就是最高的值,不可能超过他。

接下来的x是用来存储a i+1 / c的。

接下来就是确定这次的*a i*分成几份

c = max( c , 1ll );

这个就是防止出现x分成0.114514份的。

(网友::confused: )

接下来就是统计,很简单吧。

接下来就是写其他的初始化和输入了

初始化:

#include <bits/stdc++.h>
using namespace std;
int t,n,a[200010];
const int mod=1e9+7;

输入:

cin>>n;
for(int i=1;i<=n;i++){
	cin>>a[i];
}

接下来就没有了,这题就是基本的思维题,代码3分钟,思考两年半。

总代码

#include <bits/stdc++.h>
using namespace std;
int t,n,a[200010];
const int moduled=1e9+7;
int main()
{
	while(cin>>t){
	while(t--){
		cin>>n;
		memset(a,0x3f,sizeof(a));
		for(int i=1;i<=n;i++){
			cin>>a[i];
		}
		long long res=0,c=1;
		for(int i=n-1;i>=1;i--){
			int x=a[i+1]/c;
			c=(a[i]+x-1)/x;
			c=max(c,1ll);
			res+=c-1;
		}
		cout<<res<<" ";
	}}
	return 0;
}

拜拜 :raised_hand:

2 个赞

还带个2次元
6。

2 个赞

6不6

3 个赞

2次元牛逼

2 个赞

六比哦

2 个赞

《AI作图》

2 个赞