1012 Luxury cruise ship
s题意,给一个n 若存在a,b,c满足7a+31b+365c=n,求a+b+c的最小值s,否则输出-1
思路:要使得a+b+c的值最小,应使得c尽可能的大.容易想到,s(n)=s(365+n)-1 (前提是s(n)存在)
如果能得到i∈[1,365)的所有解s(i),那么对于所有n>0的解都可以算到。但显然存在很多的i满足s(i)=-1。我们可以设计一个函数count(x)处理n<365时的情况,再对n>=365的情况另外考虑
详细细节见代码
AC代码:
#include <stdio.h>
typedef long long ll;
int g[7]={0,5,3,1,6,4,2};
//31*0%7=0;
//31*5%7==1;
//31*3%7==2...
ll count(ll n);
int main()
{
ll t;
scanf("%lld",&t);
ll coins;
ll a[365]={0};
//储存365到729的结果。根据同余的知识, 可知n>=7*31(不一定是最小的)时,7*a+31*b一定有非负数解,
//从count函数也可以看出,给的n>=7*31时,a,b>=0. 所以a∈[365,730)时都是有解的
for(ll i=0;i<365;i++){
if(count(i)==-1){
a[i]=count(i+365);
}
else{
a[i]=count(i)+1;
}
}
for(ll i=0;i<t;i++){
scanf("%lld",&coins);
if(coins<365){
printf("%lld",count(coins));
}
else if(coins>=365&&coins<730){
printf("%lld",a[coins%365]);
}
else{
ll mod=coins%365;
ll t=(coins-mod)/365;
t--;
printf("%lld",t+a[mod]);
}
putchar('\n');
}
}
ll count(ll n){//对n%7的值进行分析,g[n%7]表示需要的31最小数量
ll a=0,b=0;
b=g[n%7];
a=(n-31*b)/7;
if(b*31>n) return -1;//意味着a<0
if(a>=31){//例如a=50,b=5,显然a=50-1*31=19,b=5+1*7=12是更最的解。
b+=7*(a/31);
a%=31;
}
return a+b;
}