• UVALive.3708 Graveyard (思维题)


    UVALive.3708 Graveyard (思维题)

    题意分析

    这标题真悲伤,墓地。
    在周长为1e4的圆周上等距分布着n个雕塑,现在要加入进来m个雕塑,最终还要使得这n+m个雕塑等距,那么原来的n个雕塑移动的最小距离是多少。

    W=W 依旧没思路,看了题解学习此种技巧。

    首先原先给出的n个雕塑中有一个假定不动。然后剩余的n-1的个雕塑移动到最近的目标点。目标点的定义如下:
    将原圆周等距分为n+m份,每一份的分界点为一个位置,即目标点。那么难点就在于如何判断是最近的呢,这里用到的方法就是按比例扩大+下取整

    刚才说过分为n+m份,那么我们规定那个不动的雕像为0,其他的目标点,依次标记为1,2,3……(n+m-1)。然后按照这样的比例,标记出原先的n个点的位置。这样的标记实际上已经完成了比例的放大,放大比为原来:现在 = 1:(n+m).

    放大完成后,我们只需要求出原来和现在的位置差多少就行了:
    原来第i个雕塑的位置为
    pos = i / n * (n+m) ps:要放大n+m倍
    然后要移动到的目标点是 floor(pos + 0.5 )
    这两者差的绝对值,就是需要在圆周上移动的比例,注意这里是比例,不是实际的距离,也就是说最后在输出的时候还需要乘1e4.

    为何+0.5在下取整就是目标点呢?
    不放假设,有一个雕塑在1.01, 其+0.5后为1.51, 下取整完为1,即离它最近的应该是1那个目标点;在比如说有一个雕塑在1.49,+0.5后为1.99,离它最近的也是1那个目标点,而不是2. 不难看出+0.5在下取整是求最近的目标点。

    最后,将求出的比例累加,再乘1e4输出即可,注意保留4位小数。

    代码总览

    #include <cstdio>
    #include <cmath>
    using namespace std;
    int main()
    {
        int n,m;
        while(scanf("%d%d",&n,&m) != EOF){
            double pos = 0,ans = 0;
            for(int i =1; i<n; ++i){
               pos = 1.0*i/n *(n+m); ans += fabs(pos -floor(pos+0.5))/(n+m);}
            printf("%.4f
    ",ans*10000);
        }
        return 0;
    }
  • 相关阅读:
    SpringBoot--日期格式化
    SpringBoot--使用redis实现分布式限流
    SpringBoot--集成Shiro
    xxl-job搭建、部署、SpringBoot集成xxl-job
    SpringBoot--使用socket搭建聊天室
    SpringBoot--数据库管理与迁移(LiquiBase)
    SpringBoot--防止重复提交(锁机制---本地锁、分布式锁)
    Springboot--元注解及自定义注解(表单验证)
    java类对象的初始化顺序
    java23种设计模式(三)单例模式
  • 原文地址:https://www.cnblogs.com/pengwill/p/7367131.html
Copyright © 2020-2023  润新知