题意:给两个数字n,m,求i<=k<=m的数中,求后缀0最多的数,假如数有多个,那么求最大的,比如1200和13100,那么要13100,要是1000,和1200,那么要1000,因为它的0最多

思路一:首先我们能想要求最多的后缀0,那么就是要先求最与m接近的有最多0的数,比如10,100,1000这些,然后再在这个数的基础上在不改变后缀0数目的基础上,想尽办法求导最大

代码:

#include<bits/stdc++.h>
using namespace std;

typedef unsigned long long ll;

void test()
{
ll n,m;cin>>n>>m;

ll sum2=1;
ll res=10;
for(int i=1;;i++)
{
ll sum1=lcm(res,n)/n;
if(sum1>m) break;
res*=10;
sum2=sum1;
}

ll sum=sum2;
for(int i=1;;i++)
{
if(sum+sum2>m) break;
sum+=sum2;
}

cout<<sum*n<<endl;
}
int main()
{
int T;cin>>T;
while(T--)
{
test();
}
return 0;
}

PS:我觉得必须吐槽一下,最初我以为我的思路是错的,因为每到案例三就会超时,后面翻找答案的时候,我发现了和我一样的思路,我看完人都傻了,凭什么这个是对的呐,随后我进行了测试,假如是数据范围是long long,那么时间就会超时?????,这个范围还是太小了,离谱,还有,假如你自己写个gcd,或者是lcm,那么还是超时,只有使用C++17以上才有的lcm,才不会超时,我去,真特么。。。。,另一种做法稍后再补,需要去理解一下

 思路二:因为10=2*5,所以我们应该先去计算它是由多少个2和5组成的,假如2多,那么就补5,假如5多,那么就补2,直到2和5一样多的时候,这个时候它就是10的倍数了再给它乘10,判断是否大于m,0也一定是最多的,继续补0,给它乘10,直到大于m,假如大于m,那就会退回去,不再乘10,而是遍历从1-9之间寻找哪个最大然后输出。PS:假如说在补2或5的时候出现大于m的情况,那么就回退输出

代码:

#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<string.h>
typedef long long ll;
using namespace std;
const int N = 2e5+10;
const int mod = 1e9+7;
ll a[N],b[N],c[N];
//string s1[N],s2[N],s3[N];
int main(void)
{
int t;
cin >> t;
while(t--)
{
ll n,m;
cin >> n >> m;
ll k=1;
int c2=0,c5=0;
int nn = n;
while(nn%2==0)
{
c2++;
nn/=2;
}
nn=n;
while(nn%5==0)
{
c5++;
nn/=5;
}
int d = abs(c2-c5);
if(c2>c5)
{
while(d--&&k*5<=m)
{
k*=5;
}
}
else
{
while(d--&&k*2<=m)
{
k*=2;
}
}
//cout << k << endl;
while(k*10<=m)
{
k*=10;
}
for(int i=1;i<=10;i++)
{
if(k*i>m)
{
k*=(i-1);
break;
}
}
cout << n*k << endl;
}
return 0;
}

PS:这个思路确实很新奇,从范围来说也不需要unsigned long long,时间复杂度也不容易超

 

posted on 2023-12-30 13:37  塔罗-太阳  阅读(9)  评论(0)    收藏  举报