Three Integers(暴力,行走在TLE的边缘)

VJ链接

题意:

对三个数a,b,c,进行若干次操作,每次操作只能对其中一个数进行+1或-1。同一个数可进行多次操作。问使得b能整除a且c能整除b的最少操作次数。(1≤a≤b≤c≤10000)

思路:

由于数据范围较小,且a和c都可以用b求得,可以暴力枚举b的所有情况,然后记录每种情况需要进行操作的次数。保留最小的一组即可。就是假设b已知的情况下去推a和c。
具体做法:

1.a用b来表示以及对a操作的次数实现:

b既定时,由于a%b==0,则a必然是b的因数,枚举b的所有因数,其中与a差值最小的那个因数即为最终的a,它们的差值就是需要对题中输入的a的操作次数。
注意枚举b的因数时,范围取1~sqrt(b),每次计算两个数

2.c用b表示以及对c的操作次数实现:

c=k*b(k=1,2,3,4…), 求与c最接近的b的整数倍即可,略

3 关于b的枚举范围:1~c+r ,r是个大概值,用于容错,实测200即可

但是r一定要有,为什么?我也不知道我为什么wa了六次,有明白的大佬希望能艾特我,不胜感激。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
int t,q,w,e;
int ab(int x) //绝对值
{
    return x=x>0?x:-1*x;
}
int sea(int x,int sp) //寻找与sp最接近的,x的因数值
{
    int mn=inf,s,j,r;
    for(int i=1; i<=sqrt(x); i++)
        if(x%i==0)
        {
            j=x/i;  //i,j,一次算俩
            r=ab(i-sp);
            if(mn>r)
            {
                mn=r;
                s=i;
            }
            r=ab(j-sp);
            if(mn>r)
            {
                mn=r;
                s=j;
            }
        }
    return s;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&q,&w,&e);
        int X,Y,Z,minn=inf,y,y1;  //X,Y,Z最终保留的abc值,minn:最少操作次数
        for(int k=1; k<=e+100; k++) //b的范围,一定要扩充一下
        {
            int ans=0,a=q,b=w,c=e;//ans:每次的操做次数和
            ans+=ab(b-k);//b需要的操作数
            b=k;

            if(c%k!=0)//省时间
            {
                y=c/k*k;
                ans+=min(c-y,y+k-c);
                c=(c-y)>(y+k-c)?y+k:y;//b求c
            }

            if(b%a!=0)
            {
                y1=sea(k,a);//b求a
                ans+=ab(y1-a);
                a=y1;
            }

            if(minn>ans&&c>=b&&b>=a)//因为b从1开始,但b<a没有意义
            {
                minn=ans;
                X=a,Y=b,Z=c;
            }
        }
        printf("%d\n%d %d %d\n",minn,X,Y,Z);
    }
    return 0;
}

发布了85 篇原创文章 · 获赞 10 · 访问量 5240

猜你喜欢

转载自blog.csdn.net/riversuer/article/details/104581916