2020.10.04蓝桥测试

加速输入代码

std::ios::sync_with_stdio(0);cin.tie(0);

A跑步训练

在这里插入图片描述
这里可以口算:答案为:3880.

10000 / (600-300) == 33.33
33*(600-300) = 9900
10000 - 9900 + 300 = 400 < 600
所以时间为32*2*60 + 400/10 = 3880

也可以写程序模拟:

energy = 10000
min = 0
second = 0
while(energy):
    min += 1
    if min % 2 == 1:
        if energy > 600 :
            energy -= 600
        else:    //这里就是/
            min -= 1
            second = energy/10
            energy = 0
    else:
        energy += 300
    if energy <= 0:
        break
print(min*60+second)


B: 合并检测

在这里插入图片描述

#include <stdio.h>
int main()
{
    double min=101;//最少组数 
    double zu,k,kmin;//zu当前组数,k组数,kmin最小组数 
    //假设99人1人感染
    //printf("%f\n",min);
    for(k=0;k<100;k++)
    {
        zu=(100/k)+k;
        //printf("%f",zu);
        if(zu<min)
        {
          min=zu;
          kmin=k;
        }

    }

    printf("min:%f\n",min);
	printf("kmin:%f",kmin);
    return 0;
}

在这里插入图片描述
手写:n/k+0.01nk—有n/k组,最坏0.01*n组有人,每组k次测试(每人都有一个组)

C: 分配口罩

在这里插入图片描述

package competition4;

public class Distribution2
{
	public static int[] arr =
		{ 9090400, 8499400, 5926800, 8547000, 4958200, 4422600, 5751200, 
				4175600, 6309600, 5865200, 6604400, 4635000,
				10663400, 8087200, 4554000 };
	
	public static int min=Integer.MAX_VALUE;
	public static int sum=0;
	public static boolean[] visited=new boolean[arr.length];
	
	public static void main(String[] args)
	{
		for(int x=0;x<arr.length;x++)
		{
			sum +=arr[x];
		}
		dfs(0);
		System.out.println(min);
	}
	public static void dfs(int index)
	{
		if(index>=sum/2)
		{
			min = Math.min(min, Math.abs(sum-index*2));
			return;
		}
		for(int x=0;x<arr.length;x++)
		{
			if(!visited[x])
			{
				visited[x]=true;
				dfs(index+arr[x]);
				visited[x]=false;
			}
		}
	}
}
现在要把这所有的数据分配给两家医院,要使两家医院分配的口罩的差值最小,假设所有口罩为sum,那么一家医院的口罩数目会小于sum/2,一家会大于sum/2,设小于的为lesssum,大于的为greatersum,就有差值 = greatersum - lesssum = ( sum/2 - lesssum ) * 2 = ( greatersum - sum/2 ) * 2
所有题目就可以变相理解成:一个背包的大小为sum/2,现在我要把上面的口罩放入背包,求放入背包的最大值,求出了最大值就可以求出和sum/2的差值了,乘以2就是题目要求的值了

[nb](https://blog.csdn.net/weixin_43846904/article/details/108974218)

代码
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]));
    }
}

D: 矩阵

在这里插入图片描述

第十一届蓝桥杯 ——矩阵目前最喜欢的题解,DP,i是第一行数量,j是第二行数量

DP进行方案数计数,dp(i,j)表示前i个数选其中j个放入第一行,转移策略如代码中注释所示。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2500;
int dp[maxn][maxn];//dp[i][j]表示前i个数放其中j个到第一行的方案数; 
int main()
{
	int i,j;
	memset(dp,0,sizeof(dp));
	dp[1][1]=1;//1肯定放到第一行(若放到第二行不可能比第一行大)
	//维护dp表的下三角即可(j>i的上三角无意义)
	//dp策略:
	//1.数字放在第一行肯定可以,后面遍历的数字越来越大;
	//2.数字放在第二行的条件是目前第一行的数字比第二行多,
	//	因为若目前少,则之后肯定得有更大的数放到第一行,与要求冲突 
	for(i=2;i<=2020;i++)
	{
		for(j=1;j<=i;j++)
		{
			dp[i][j]=(dp[i][j]+dp[i-1][j-1])%2020;//放到第一行; 
			if(i-j<=j)//i-j为放第二行的数字数,即放第二行的数字数小于第一行的数字数的情况(此时i是正要遍历的,所以等号可取) 
			{
				//放到第二行; 
				dp[i][j]=(dp[i][j]+dp[i-1][j])%2020;
			} 
		}
	}
	printf("%d\n",dp[2020][1010]);
	return 0;
 } //1340

【Java编程】Java中的大整数计算
java 大整数
卡特兰数详讲
卡特兰数 — 计数的映射方法的伟大胜利
python实现筛法求素数
Python取整——向上取整、向下取整、四舍五入取整、向0取整
两个有趣且特殊的Python取整:int()、整除"//"
python一定记得整除//
没有数组,只能列表
catalan=[1,1,2]
catalan.append(y)

卡特兰数:
这个转成python就能求,数组用list
a=[1,1,2]
加入用append
a.append(x)

卡特兰数c++

#include <iostream>
#include<bits/stdc++.h> 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
long long catalan[2025]={0}; 
int main(int argc, char *argv[]) {
	catalan[0]=catalan[1]=1;
	catalan[2]=2;
	for(int i=3;i<100;i++)
	{
		for(int j=0;j<i;j++)
		{
			catalan[i]+=catalan[j]*catalan[i-1-j];//这是一种求法
		}	
	}
	for(int i=0;i<100;i++)
	{
		cout<<catalan[i]<<endl;
	}
//	cout<<0<<endl;
	return 0;
}
卡特兰数java

这里一定要建一个,不然后面直接调用会空指针异常

import java.io.*;
import java.math.*;
class test
{
    public static void main (String[] args) throws java.lang.Exception
    {
        BigInteger []a=new BigInteger[2025];
        a[0]=BigInteger.valueOf(1);
        a[1]=BigInteger.valueOf(1);
        a[2]=BigInteger.valueOf(2);
        for(int i=3;i<2020;i++)
        {
            a[i]= BigInteger.valueOf(0);//这里一定要建一个,不然后面直接调用会空指针异常
            for(int j=0;j<i;j++)
            {
                a[i]=a[i].add(a[j].multiply(a[i-1-j]));
            }
        }
        for(int i=0;i<101;i++)
        {
            System.out.println(a[i]);
        }
    }
}

E完美平方数

【问题】
如果整个整数X本身是完全平方数,同时它的每一位数字也都是完全平方数,我们就称X是完美平方数。 前几个完美平方数是 0、1、4、9、100、144…
请你计算第 2020 个完美平方数是多少?
暴力搜索代码:
///到目前已经跑了2.5个点了
在这里插入图片描述

tot = 7
i =13
ans=0
while(tot<2020):
    num=0
    num=i*i
    while(num!=0):
        now=0
        now=num%10
        if now!=0 and now!=1 and now!=4 and now!=9:
            break
        num//=10
        
    if num==0:
        tot+=1
    if tot==2020:
        ans=i*i
    i+=1
    if i%100000==0:
        print('i:%d tot:%d ans:%d'%(i,tot,ans))
print(ans)

F解码

在这里插入图片描述

#include <iostream>
#include<bits/stdc++.h> 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
int isnumber(char a){
	if(a<='9'&&a>='0')
	{
		return 1;
	}
	
	return 0;
}
int main(int argc, char *argv[]) {
	
	char str[1000];
	
	cin>>str;
	char buf;
	int n=strlen(str);
	for(int i=0;i<n;i++)
	{
		if(!isnumber(str[i]))
		{
			buf=str[i];
			cout<<str[i];
		}else{
			for(int j=0;j<str[i]-'0'-1;j++)
			{
				cout<<buf;
			}
		}
		
	}
	
	
	return 0;
}

G: 走方格

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
#define x first
#define y second
#define mem(h) memset(h,-1,sizeof h)
#define mcp(a,b) memcpy(a,b,sizeof b)
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int>PII;
typedef pair<double,double>PDD;
namespace IO{
	inline LL read(){
		LL o=0,f=1;char c=getchar();
		while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
		while(c>='0'&&c<='9'){o=o*10+c-'0';c=getchar();}
		return o*f;
	}
}using namespace IO;
//#############以上是自定义技巧(可忽略)##########
const int N=1e4+7,M=2e5+7,INF=0x3f3f3f3f,mod=1e8+7,P=131;
int n,m;
int dp[N][N];
int main(){
	cin>>n>>m;
	dp[1][1]=1;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(i==1&&j==1)continue;
			if(i%2!=0||j%2!=0){//如果有一个不为偶数
				dp[i][j]+=dp[i-1][j];//可以从上面转移过来
				dp[i][j]+=dp[i][j-1];//可以从左边转移过来
			}else{//否则就进不来,为0
				dp[i][j]=0;
			}
		}
	}
	cout<<dp[n][m]<<endl;
	return 0;
}

自己写的递归代码

#include <iostream>
#include<bits/stdc++.h> 
using namespace std;
#define maxn 10000
int dp[maxn][maxn]={0};
int zou(int m,int n){
	cout<<"m "<<m<<"n:"<<n<<endl;
	if(m==1&&n==1)
	{
		dp[m][n]=1;
		return 1;
	}
	if(m%2==0&&n%2==0)
	{
		dp[m][n]=0;
		return 0;
	}
	if(m==1)
	{
		return 1;
	}
	if(n==1)
	{
		return 1;
	}
	if(dp[m][n]!=0){
		return dp[m][n];
	}
	
	
	
	dp[m][n]=zou(m-1,n)+zou(m,n-1);
	return dp[m][n];
}

int main(int argc, char *argv[]) {
	int m,n;
	cin>>m>>n;
	
	cout<<zou(m,n);
	cout<<endl;
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cout<<dp[i][j]<<" ";
		}
		cout<<endl;
	}
	return 0;
}

H: 整数小拼接

在这里插入图片描述
我的第一遍代码

#include <iostream>//应该还可以优化,这里用的式=是直接求出来,但应该会爆,用取K的每一位(比如40+i肯定大于K=33) //还可以剪枝
#include<bits/stdc++.h> 
using namespace std;
#define maxn 10000
int val[maxn]={0};
int weishumem[maxn]={0};
int weishu(int i)
{
	int n=val[i];
	if(weishumem[i]!=0)
	{
		return weishumem[i];
	}
	int sum=0;
	while(n)
	{
		n/=10;
		sum++;
	}
	weishumem[i]=sum;
	return sum;
}
int shicifang(int n){
	int ans=1;
	for(int j=0;j<n;j++)
	{
		ans*=10;
	}
	return ans;
}
int main(int argc, char *argv[]) {
	int K,n;
	cin>>n>>K;
	for(int i=1;i<=n;i++)
	{
		cin>>val[i];
	}
	///开拼 +
	int sum=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=i;j<=n;j++)///这里很重要 
		{
			if(i==j)
			{
				continue;
			}
			
			int weishu_i=weishu(val[i]);
			int weishu_j=weishu(val[j]);
			int shicifang_i=shicifang(weishu_i)*val[j];
			int shicifang_j=shicifang(weishu_j)*val[i];
			///i在后 
			if(shicifang_i+val[i]<=K)
			{
				sum++;
			}
			if(shicifang_j+val[j]<=K)
			{
				sum++;
			}
			
		}
	}
	cout<<sum;
	return 0;
}

https://www.cnblogs.com/sddr/p/13258916.html
典型的排列问题,直接上八皇后的模板,事实上所有的排列问题,都能用它解决,只需要在排列好两个数的时候,进行拼接,比较大小,计数即可,唯一害怕的就是时间过不了

#include<iostream>
using namespace std;
int n,k,sum=0;
int a[5];
int b[100005];
bool isok(int r){
	for(int i=0;i<r;i++){
		if(a[i]==a[r]){
			return false;
		}
	}
	return true;
}
void dfs(int r){
	if(r==2){
		int w=1;
		while(b[a[1]]/w){
			w *= 10;
		}
		int cache = b[a[0]]*w+b[a[1]];
		if(cache<k){
			sum++;
		}
		return ;
	}
	for(int i=0;i<4;i++){
		a[r]=i;
		if(isok(r)){
			dfs(r+1);
		}
	}
}
int main()
{
	cin >> n >> k;
	for(int i=0;i<n;i++){
		cin >> b[i];
	}
	dfs(0);
	cout << sum;
	return 0;
}

I: 超级胶水

在这里插入图片描述
应该就是矩阵连乘

动态规划:矩阵连乘问题(C++实现,含备忘录方法)
斜着遍历代码
在这里插入图片描述

#include <iostream>
#include<bits/stdc++.h> 
using namespace std;
#define maxn 10000
int dp[maxn][maxn]={0};
int val[maxn]={0};
int dp_hei[maxn][maxn]={0};
int weiji(int m,int n)
{
	if(dp_hei[m][n]!=0)
	return dp_hei[m][n];
	int sum=0;
	for(int i=m;i<=n;i++)
	{
		sum+=val[i];
	}
	dp_hei[m][n]=sum;
	return sum;
}
int dp_m(int m,int n)
{
	if(dp[m][n]!=0)
	{
		return dp[m][n];
	}
	if(m==n)
	{
		return 0;
	}
	int min_k=maxn*10;
	for(int k=m;k<n;k++)
	{
		min_k=min(min_k,dp_m(m,k)+dp_m(k+1,n)+weiji(m,k)*weiji(k+1,n));///这里从m开始,重量计算也dp
	}
	dp[m][n]=min_k;
	
	return dp[m][n];
}

int main(int argc, char *argv[]) {
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>val[i];
	}
	cout<<dp_m(1,n);
	return 0;
}

J: 网络分析

在这里插入图片描述
https://blog.csdn.net/weixin_43738764/article/details/109035131

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值