16省8-四平方和
四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多4个正整数的平方和。
如果把0包括进去,就正好可以表示为4个数的平方和。
比如:
5 = 0^2 + 0^2 + 1^2 + 2^2
7 = 1^2 + 1^2 + 1^2 + 2^2
(^符号表示乘方的意思)
对于一个给定的正整数,可能存在多种平方和的表示法。
要求你对4个数排序:
0 <= a <= b <= c <= d
并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法
程序输入为一个正整数N (N<5000000)
要求输出4个非负整数,按从小到大排序,中间用空格分开。
例子
输入
5
输出
0 0 1 2
输入
12
输出
0 2 2 2
输入
773535
输出
1 1 267 838
题目限制
单输出时间限制< 1s
峰值内存消耗 < 256M
CPU消耗 < 3000ms
枚举暴力但会超时,75分代码
#include <bits/stdc++.h>
using namespace std;
int main()
{ int i,j,k,l;
int n;
cin>>n;
for(i=0;i*i<n;i++){
for(j=0;j*j<n;j++){
for(k=0;k*k<n;k++){
for(l=0;l*l<n;l++){
if(n==i*i+j*j+k*k+l*l) {
printf("%d %d %d %d\n",i,j,k,l);
return 0;
}
}
}
}
}
return 0;
}
优化,100分代码
#include<bits/stdc++.h>
using namespace std;
int n;
map<int,int>cache;
int main(){
cin>>n;
for(int c=0;c*c<=n/2;c++){
for(int d=c;c*c+d*d<=n;d++){
if(cache.find(c*c+d*d)==cache.end())//找不着的时候就存进去,已经存在就不用存进去
cache[c*c+d*d]=c;
}
}
for(int a=0;a*a<=n/4;a++){
for(int b=a;a*a+b*b<=n/2;b++){
if(cache.find(n-a*a-b*b)!=cache.end()){//找得到
int c=cache[n-a*a-b*b];
int d=int(sqrt(n-a*a-b*b-c*c));
printf("%d %d %d %d",a,b,c,d);
return 0;
}
}
}
return 0;}
不太懂map<int,int>cache
参考博客里面的一些map相关的函数可以学起来记住。
下面这里说出了map的功能
2、map的功能
自动建立Key - value的对应。key和value可以是任意你需要的类型。
根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多
查找10次,1,000,000个记录,最多查找20次。
快速插入Key - Value记录。
快速删除记录
根据Key修改value记录。
遍历所有记录。
有点类似python里的字典
斐波拉契数列,迭代算法和递归算法
斐波那契数列:1、1、2、3、5、8、13…
使用迭代算法和递归算法都可以实现斐波那契数列,输出数列中的第N项,但是由于递归算法在计算时存在着大量的重复计算,所以在N值很大时,可能会造成内存的溢出,以及计算时间较长的情况出现,在使用迭代算法的情况下同样可以实现计算斐波那契数列第N项的功能,代码示例如下
递归(recursion)算法:
#include<bits/stdc++.h>
using namespace std;
int fibnace(int n){
if(n==0) return 0;
if(n==1) return 1;
else return fibnace(n-1)+fibnace(n-2);
}
int main(){
cout<<fibnace(40)<<endl;
return 0;}
迭代(iteratin)算法:
#include<bits/stdc++.h>
using namespace std;
int fibonacciteration(int num){
if(num==0) return 0;
if(num==1||num==2) return 1;
int first=1,second=1,third=0;
for(int i=3;i<=num;i++){
third=first+second;
first=second;
second=third;
}
return third;
}
int main(){
cout<<fibonacciteration(40)<<endl;
}
比较:当n小的时候,递归和迭代时间差异基本不大,当n大的时候,时间差异明显较大,列入当n=40的时候,递归就明显变得很慢。所以在n大时,迭代算法时间上较快。
20省1-Jb5- 斐波那契数列最大公约数
【问题描述】
斐波那契数列满足 F1 = F2 = 1,从 F3 开始有 Fn = Fn−1 +Fn−2。
请你计算 GCD(F2020,F520),其中 GCD(A,B) 表示 A 和 B 的最大公约数。
【输入】
没有输入。
【输出】
输出一个整数。
思路
数学中有一个重要的定理 gcd(f(n),f(m))=f(gcd(n,m))
可以简化该题
#include<bits/stdc++.h>
using namespace std;
int fibonacciteration(int num){
if(num==0) return 0;
if(num==1||num==2) return 1;
int first=1,second=1,third=0;
for(int i=3;i<=num;i++){
third=first+second;
first=second;
second=third;
}
return third;
}
int gcd(int i,int j){
return (!j)?i:gcd(j,i%j);
}
int main(){
cout<<fibonacciteration(gcd(2020,520))<<endl;
}
20省1-Jb4- 分配口罩
【问题描述】
某市市长获得了若干批口罩,每一批口罩的数目如下:
9090400
8499400
5926800
8547000
4958200
4422600
5751200
4175600
6309600
5865200
6604400
4635000
10663400
8087200
4554000
现在市长要把口罩分配给市内的2所医院。
由于物流限制,每一批口罩只能全部分配给其中一家医院。
市长希望2所医院获得的口罩总数之差越小越好。
请你计算这个差最小是多少?
【输入】
没有输入。
【输出】
输出一个整数。
思路
我当时审题有点错误,我以为是每家医院从这15个里面拿出一个送,也就是我当时求了15个数两俩差最小,结果是错的。
想也知道,按照蓝桥杯传统习俗,肯定是暴力之类可以解决大部分题目。
题解是,15批全部发送给2个医院,然后求最小差。
解题
这个题就是把数组分成两个部分,求两部分和最小值的包装版本,可以用暴力dfs也可以dp(0-1背包作背包容量为sum/2的dp),结果填空且只有15个数,直接暴力搜即可。
dfs
#include<bits/stdc++.h>
using namespace std;
long long mask[15]={9090400,8499400,5926800,8547000,4958200,4422600,5751200,4175600,6309600,5865200,6604400,4635000,10663400,8087200,4554000};
long long sum=0;
long long minn=0xffffff;
int dfs(int x,long long now){
if(x>=15){
minn=min(minn,abs(sum-2*now));
return 0;
}
dfs(x+1,now+mask[x]);
dfs(x+1,now);
}
int main(){
int i;
for(i=0;i<15;i++){
sum+=mask[i];
}
dfs(0,0);
printf("%lld",minn);
return 0;}
dp
public class Main {
public static void main(String[] args) {
int sum = 0 , su = 0;
int[] nums = {0, 9090400, 8499400, 5926800, 8547000, 4958200,
4422600, 5751200, 4175600, 6309600, 5865200, 6604400, 4635000,
10663400, 8087200, 4554000};
for (int i = 0; i < nums.length; i++) {
sum = sum + nums[i];
}
su = sum / 2;
int[] dp = new int[su+1];
for (int i = 1; i < nums.length; i++) {
for (int j = su; j >= nums[i]; j--) {
dp[j] = Math.max(dp[j] , dp[j-nums[i]] + nums[i]);
}
}
System.out.println(2 * (su - dp[su]));
}
}