#poj:Fair Distribution

poj:Fair Distribution

#题目描述
在这里插入图片描述

#大概意思要你找到一个最短的方式来使得n * k = m 成立 n只能减小 m只能增加 k为任意一整数
#n减少的数加上m增加的数的和最小
#看着好像只能暴力的算 但是定睛一看 范围 1e8 直接暴力能想到会超时 自己写也是各种优化都来试试撞运气还是卡时间 还要优化算法

#知识点
分块 (我是没看出来-别的大佬说的(⊙ˍ⊙))

#代码

#include<bits/stdc++.h>
using namespace std;
#define maxn 1e9
int n,m;

int main()
{
    int t;
    cin >> t;
    for(int i=1; i<=t; i++)
    {
        cin >> n >> m;
        if(m % n == 0)
        {
            cout << 0 <<endl;
            continue;
        }
        if(m < n)
        {
            cout <<n - m <<endl;
            continue;
        }
        else//问题是咋这样想啊  一般都都只会想到下面的i是x   这个将temp也用上了  能用temp 就用temp 否则就用i
        {
            int ans = maxn;
            for(int i=1; i<=n&&i*i <= m; i++) ///!!! i*i 关键  这个限制条件效果很好
            {
                int temp = (m+i-1)/i;///向上取整  temp  和 i 都有可能是x   x * k = m
                if(n >= temp)//temp 是x
                {
                    int cnt = (m + temp - 1)/temp;//cnt 是 k 向上取整过的  所以*x后 会大于m
                    ans = min(ans, min(n-i,n-temp+cnt*temp - m));//min 中 n-i为整除的情况 后一种就是正常情况
                }
                else // i 是x  temp 太大了 不能为n  x应该小于n
                {
                    ans = min(ans,n-i+i*temp-m);//!!! 这个temp是向上取整过的  否则要 n-i + m - m%i
                }
            }
            cout << ans <<endl;
        }
    }
    return 0;
}

#总结
学习了大佬的算法 一眼看过去看不懂 蒟蒻(汗 ~ : P)自己分析了好久才弄的 但是还是不知道为什么要这样弄 先学会了再说吧 不会就自己带个数据跑一遍就又会了一点点 (⊙.⊙) 就嗯推 没那个悟性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值