题目链接: 传送门
题目贴上:
题意: 给你一个整数n,这个n是否可以写成 a x 3+b x 5+c x 7=n这种形式(a,b,c>=0),如果答案有多种,随便输出一种,如果不存在,就输出-1
思路:
我们观察一下可以可以对a,b,c大致规划一个范围(因为题目n是<=1000的整数),a最大是333,因为333x3=999,和1000最接近,b最大是200,c最大是142。
我们先试一下三种循环的暴力方法吧,我试了试,直接在test5,超时了
(下面是超时代码)
#include<bits/stdc++.h>
namespace mySpace{
typedef long long int ll;
typedef long double ld;
typedef double db;
//typedef __int64 int bi;
//nth_element(first,pos,end) =>STL function ,求第pos小的元素
#define fori(a,b,c) for(int a=b;a<=c;++a)
#define me(a) memset(a,0,sizeof a)
#define Mod 1000000009
#define exp 1e-8
#define fi first
#define se second
#define sc_int(x) scanf("%d",&x)
#define sc_db(x) scanf("%lf",&x)
#define sc_str(x) scanf("%s",x)
#define sc_bi(x) scanf("%I64d",&x)
#define pr_int(x) printf("%d\n",x)
#define pr_bi(x) printf("%lld\n",x)
const int INF = 0x7fffffff;
const int MAX1 = 2e5+10;
const int MAX2 = 1e6+10;
const int MAX3 = 2e6+10;
//#define IS std::ios::sync_with_stdio(false)
//#define OS std::cin.tie(NULL)
void readFoler()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
}
void closeFoler()
{
fclose(stdin);
fclose(stdout);
}
}
using namespace std;
using namespace mySpace;
int main(void)
{
int t,n;
sc_int(t);
while(t--)
{
sc_int(n);
int ok=0;
int a=0,b=0,c=0;
for(int i=0;i<=334;++i)
{
for(int j=0;j<=200;++j)
{
for(int k=0;k<=150;++k)
{
if(i*3+j*5+k*7==n){
a = i;
b = j;
c = k;
ok = 1;
goto end;
}
}
}
}
end:;
if(ok) cout<<a<<" "<<b<<" "<<c<<endl;
else cout<<"-1"<<endl;
}
}
结果:
优化: 三重循环不行,那我们就用两重循环,那怎么优化呢?
我们发现,当我们确定a和b的时候,c也是可以确定的,也就是说,假如s = n -(a x 3+b x 5);,如果 s % 7 ==0,那说明结果可以,退出两次循环,反之不行,这样子我们就实现了三重循环到两重循环的优化了。
#include<bits/stdc++.h>
namespace mySpace{
typedef long long int ll;
typedef long double ld;
typedef double db;
//typedef __int64 int bi;
//nth_element(first,pos,end) =>STL function ,求第pos小的元素
#define fori(a,b,c) for(int a=b;a<=c;++a)
#define me(a) memset(a,0,sizeof a)
#define Mod 1000000009
#define exp 1e-8
#define fi first
#define se second
#define sc_int(x) scanf("%d",&x)
#define sc_db(x) scanf("%lf",&x)
#define sc_str(x) scanf("%s",x)
#define sc_bi(x) scanf("%I64d",&x)
#define pr_int(x) printf("%d\n",x)
#define pr_bi(x) printf("%lld\n",x)
const int INF = 0x7fffffff;
const int MAX1 = 2e5+10;
const int MAX2 = 1e6+10;
const int MAX3 = 2e6+10;
//#define IS std::ios::sync_with_stdio(false)
//#define OS std::cin.tie(NULL)
void readFoler()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
}
void closeFoler()
{
fclose(stdin);
fclose(stdout);
}
}
using namespace std;
using namespace mySpace;
int main(void)
{
int t,n;
sc_int(t);
while(t--)
{
sc_int(n);
int ok=0;
int a=0,b=0,c=0;
for(int i=0;i<=334;++i)
{
for(int j=0;j<=201;++j)
{
if(n-(i*3+j*5)>=0&&(n-(i*3+j*5))%7==0){
//注意前面一定要要>=0!!!
a = i;
b = j;
c = (n-(i*3+j*5))/7;
ok = 1;
goto end; //goto 是瞬间转移到某某位置,比如这里是转移到end位置,也就相当于退出两重循环了
}
}
}
end:;
if(ok) cout<<a<<" "<<b<<" "<<c<<endl;
else cout<<"-1"<<endl;
}
}
结果:
然后顺利过了,这道题目题目虽然比较简单,但我们要知道,循环过多,我们一定要想办法优化他,不要为了做题而做题,要举一反三,想想一题多解,更好的优化,这样子以后做题我们就有更多后路了!