Annoying Present(思维题)

Annoying Present

Alice got an array of length n

as a birthday present once again! This is the third year in a row!

And what is more disappointing, it is overwhelmengly boring, filled entirely with zeros. Bob decided to apply some changes to the array to cheer up Alice.

Bob has chosen m
changes of the following form. For some integer numbers x and d, he chooses an arbitrary position i (1≤i≤n) and for every j∈[1,n] adds x+d⋅dist(i,j) to the value of the j-th cell. dist(i,j) is the distance between positions i and j (i.e. dist(i,j)=|i−j|, where |x| is an absolute value of x

).

For example, if Alice currently has an array [2,1,2,2]
and Bob chooses position 3 for x=−1 and d=2 then the array will become [2−1+2⋅2, 1−1+2⋅1, 2−1+2⋅0, 2−1+2⋅1] = [5,2,1,3]. Note that Bob can’t choose position i outside of the array (that is, smaller than 1 or greater than n

).

Alice will be the happiest when the elements of the array are as big as possible. Bob claimed that the arithmetic mean value of the elements will work fine as a metric.

What is the maximum arithmetic mean value Bob can achieve?

Input

The first line contains two integers n

and m (1≤n,m≤105

) — the number of elements of the array and the number of changes.

Each of the next m
lines contains two integers xi and di (−103≤xi,di≤103) — the parameters for the i

-th change.

Output

Print the maximal average arithmetic mean of the elements Bob can achieve.

Your answer is considered correct if its absolute or relative error doesn't exceed 10−6

.

Examples
Input

2 3
-1 3
0 0
-1 -4

Output

-2.500000000000000

Input

3 2
0 2
5 0

Output

7.000000000000000
题意:

给你一个初始大小为n的数组,里面的元素初始全为0,给一个数m代表m次操作,每次操作给定两个数字x,d,要求我我们对每个数组元素 ai a i 执行下面操作:
ai=ai+x+d×|ij| a i = a i + x + d × | i − j |
其中j是我们随机选定的一个固定位置,i从1-n遍历
问每次操作怎么选择这个j可以使得m次操作后n个数字的平均值最大
输出这个最大平均值

分析:

总体思路是算出m次操作后的总和ans,然后再求平均
对于每一次操作我们观察公式

ai=ai+x+d×|ij| a i = a i + x + d × | i − j |

发现x对于数字的最大值改变没有影响,因为每次操作都会加固定的x,那么每次循环开始前,我们就把总和ans先加上 n×x n × x 即可,接下来我们分析j的影响,即选定位置的影响

  • 当d > 0时:因为d大于零,所以我们为了使后面加的更大,所有就希望 |ij| | i − j | 越大越好,仔细想想我们会发现这些距离无非就是从0….到某个小于等于n-1的数(n个数最大距离n-1,两头距离),所有为了使总的距离和最大我们就应该选择最大距离最大的,所以j应该选择两头的位置,因此总的距离和就是 1+2+...+(n1)=n×(n1)2 1 + 2 + . . . + ( n − 1 ) = n × ( n − 1 ) 2 ,然后 ans+=n×(n1)2×d a n s + = n × ( n − 1 ) 2 × d
  • 当d < 0时:同理我们就会希望 |ij| | i − j | 越小越好,根据同样的思想,固定位置j应该选择中间,这样最大的距离才能最小,总的距离和才能最小,在这种情况下就又分成两种情况:
    1.当n为奇数的时候比如1 2 3 4 5,中间位置是3即 n+12 n + 1 2 ,所以距离和:

    2×[1+2+...+(n+121)] 2 × [ 1 + 2 + . . . + ( n + 1 2 − 1 ) ]
    = n214 n 2 − 1 4

    ans+=n214×d a n s + = n 2 − 1 4 × d

    2 .当n为偶数的时候,比如1 2 3 4,中间位置是 n2 n 2 ,距离和:
    [1+2+...+(n21)]×2+n2 [ 1 + 2 + . . . + ( n 2 − 1 ) ] × 2 + n 2
    = n24 n 2 4

    ans+=n24×d a n s + = n 2 4 × d

最后注意,要用long long 最后转成double,否则wa!!
我也没想清楚为啥,希望大家指点
总的来说还是很好的一道思维题

code:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
ll n,m,x,d;
int main(){
    scanf("%lld%lld",&n,&m);
    ll ans = 0;
    while(m--){
        scanf("%lld%lld",&x,&d);
        ans += n * x;
        if(d > 0){
            ans += (n - 1.0) * n / 2.0 * d;
        }
        else if(d < 0){
            if(n & 1){
                ans += (n * n - 1) / 4 * d;
            }
            else{
                ans += n * n / 4 * d;
            }
        }
    }
    printf("%.15f\n",ans*1.0/n);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用深度优先搜索(DFS)来解决这个问。首先,我们可以将问抽象为一个图,其中每个房间都是一个节点,相邻房间之间有边相连。 首先,我们需要定义一个辅助函数,用于检查给定的坐标是否在合法的范围内: ```cpp bool isValid(int x, int y, int n, int m) { return (x >= 1 && x <= n && y >= 1 && y <= m); } ``` 接下来,我们可以使用DFS来遍历所有可能的移动方式。我们从Vika的起始位置开始,依次向四个方向移动,然后递归地对每个朋友进行相同的操作。如果在递归过程中,任何一个朋友与Vika在同一个房间,则说明Vika会被抓住。 以下是完整的C++代码实现: ```cpp #include <iostream> #include <vector> using namespace std; bool isValid(int x, int y, int n, int m) { return (x >= 1 && x <= n && y >= 1 && y <= m); } bool dfs(int vx, int vy, vector<pair<int, int>>& friends, vector<vector<bool>>& visited, int n, int m) { if (vx == 0 && vy == 0) { // Vika has successfully escaped return true; } visited[vx][vy] = true; // Possible neighbors' coordinates vector<pair<int, int>> neighbors = {{vx-1, vy}, {vx+1, vy}, {vx, vy-1}, {vx, vy+1}}; for (auto neighbor : neighbors) { int nx = neighbor.first; int ny = neighbor.second; if (isValid(nx, ny, n, m) && !visited[nx][ny]) { bool caught = false; for (auto friendCoord : friends) { int fx = friendCoord.first; int fy = friendCoord.second; if (nx == fx && ny == fy) { caught = true; break; } } if (!caught && dfs(nx, ny, friends, visited, n, m)) { return true; } } } return false; } string canVikaEscape(int n, int m, int vx, int vy, vector<pair<int, int>>& friends) { vector<vector<bool>> visited(n+1, vector<bool>(m+1, false)); if (dfs(vx, vy, friends, visited, n, m)) { return "Yes"; } else { return "No"; } } int main() { int n, m, vx, vy, k; cin >> n >> m >> vx >> vy >> k; vector<pair<int, int>> friends(k); for (int i = 0; i < k; i++) { cin >> friends[i].first >> friends[i].second; } cout << canVikaEscape(n, m, vx, vy, friends) << endl; return 0; } ``` 该代码首先读取输入的n,m,vx,vy和k值。接下来,它读取k个朋友的坐标,并调用canVikaEscape函数来判断Vika是否能逃脱。最后,它输出结果。 希望这可以帮助到你!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值