2020年第一场NOI Online入门组
P1424. 文具订购
题目: 文具订购
前置数学知识(可参考下题): 若p,q两数互质,即(p,q)=1,则p和q不能凑出来的最大数是(p-1)(q-1)-1,例如p=4,q=3,那么p和q不能凑出来的最大数是5,也就是说所有比5大的数都可以被3和4表示出来,那么此题不能被表示的数只有1,2,5(0可以被表示)
因为成套数越多越好,我们假设最多k套,则n-14k一定比20小,因为如果n-14k>=20我们就一定还可以再买一套并且剩下的钱能够被凑出来(比5大),那么此时k就不是最优解了,矛盾,因此在k为最优解的前提下,n-14k一定比20小,此时我们不一定能再买一套,因为如果再买一套不一定能保证钱全部用光
整体思路: 一开始k= ⌊ n 14 ⌋ \lfloor \frac{n}{14}\rfloor ⌊14n⌋,当r=n-14k=1/2/5时,我们再拿出14凑给r,这样r=15/16/19<20,就一定可以满足要求了,然后再循环枚举abc即可,此时r一定比20小,因此时间复杂度极低
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=20;
int s[3];
int n;
int main(){
scanf("%d",&n);
if(n==1||n==2||n==5) puts("-1");
else{
int k=n/14;
int r=n-14*k;
if(r==1||r==2||r==5){
//此时要再拿一个14凑给r
k--;
r+=14;
}
memset(s,-1,sizeof(s));
for(int a=0;a*7<=r;a++){
for(int b=0;a*7+b*4<=r;b++){
if((r-a*7-b*4)%3==0){
int c=(r-a*7-b*4)/3;
if(s[0]==-1||a+b+c>s[0]+s[1]+s[2]){
s[0]=a;
s[1]=b;
s[2]=c;
}
}
}
}
printf("%d %d %d\n",k+s[0],k+s[1],k+s[2]);
}
return 0;
}
P525. 小凯的疑惑
题目: 小凯的疑惑
上题数学结论裸题
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
typedef long long LL;
using namespace std;
LL a, b;
int main()
{
scanf("%lld%lld", &a, &b);
LL res=(a-1)*(b-1)-1;
printf("%lld",res);
return 0;
}
P1425. 跑步
题目: 跑步
P900. 整数划分升级版,整数划分两种方法时间复杂度均为O( n 2 n^2 n2),本题要求做到O(nlogn)或O(n√n)
一个问题经过函数的方法转化,更有利于研究,因为已经有很多关于函数的定理了
思路: 我们记n=0的方案数为 P 0 P_0 P0,n=1的方案数为 P 1 P_1 P1,n=2的方案数为 P 2 P_2 P2,······以此类推一直到 P n P_n Pn (该序列记成{
P n P_n Pn})
则该数列的生成函数为: f ( x ) = P 0 x 0 + P 1 x 1 + P 2 x 2 + ⋯ + P n x n f(x)=P_0x^0+P_1x^1+P_2x^2+⋯+P_nx^n f(x)=P0x0+P1x1+P2x2+⋯+Pn