蓝桥杯算法训练之题记

28 篇文章 0 订阅
24 篇文章 1 订阅

链接:http://lx.lanqiao.cn/index.page
来源:蓝桥杯



算法训练 审美课(位运算)

审美课:神仙解法,位运算(自行百度题解)
在这里插入图片描述

#include <iostream>
#include <cstdio>
#include <set>
#include <queue>
#include <algorithm>
using namespace std;

typedef long long LL;
const int Max_n=(1<<20)+5;
int a[Max_n],cnt[Max_n];

int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            int t;
            scanf("%d",&t);
//每一行可以看成一个二进制数,我们把每一行按照十进制数来表示.
            a[i]=(a[i]<<1)+t
        }
        cnt[a[i]]++;//记录这个十进制数出现了几次.
    }
    int ans=0;
//每一行都是由m个01数组成,我们把它看成二进制数,我们现在需要一个所有位数都是1的一个二进制数
    int x=(1<<m)-1;
    for(int i=0;i<n;i++){
        ans+=cnt[a[i]^x];
//我们知道不管是1还是0,与1进行^操作时,相当于取反操作.(1^1=0,0^1=1)
//进行取反操作以后我们就会知道与当前这个学生不同的有多少个学生,这里我们进行了重复运算
//a与b不同,在经过a时算了一次,经过b时又算了一次,故最终结果要/2.
    }
    printf("%d\n",ans/2);
    return 0;
}

算法训练 素因子去重(数论(素数))

素因子去重:类似于欧拉函数,因为数据类型错了三次.(刚开始用素数筛来做此题,发现想法过于复杂,后来把类型改的乱七八糟.)
在这里插入图片描述

#include <iostream>
#include <cstdio>
#include <cmath>
#include <set>
#include <queue>
#include <algorithm>
using namespace std;

typedef long long LL;
const int Max_n=1000005;

LL get_ans(LL n){//数据类型
    LL ans=1;
    for(LL i=2;i<=n;i++){//此处需要注意数据类型
        if(n%i==0){//这里一直用n是因为我们找的素数一直不可能大于n
            while(n%i==0) n/=i;//选出每一个素数,类似于欧拉函数
            ans*=i;
        }
    }
    return ans;
}

int main(){
    LL n;
    scanf("%lld",&n);
    LL ans=get_ans(n);
    printf("%lld\n",ans);
    return 0;
}

算法训练 P0505(高精度 * 单精度(模板),离线计算)

P0505:高精度*单精度模板(详解见博客,附链接)
?大数模板(C/C++)地址:https://blog.csdn.net/qq_42217376/article/details/88064401 ?
?大数模板(Java)地址:https://blog.csdn.net/qq_42217376/article/details/88069217 ?
在这里插入图片描述

#include <iostream>
#include <cstdio>
#include <cmath>
#include <set>
#include <queue>
#include <algorithm>
using namespace std;

typedef long long LL;
const int Max_n=105;

struct BigNum{
    int s[3*Max_n],l;
}c[Max_n];

BigNum operator *(BigNum a,int b){
    for(int i=0;i<a.l;i++) a.s[i]*=b;
    for(int i=0;i<a.l;i++){
        a.s[i+1]+=a.s[i]/10;
        a.s[i]%=10;
    }
    while(a.s[a.l]!=0){
        a.s[a.l+1]+=a.s[a.l]/10;
        a.s[a.l]%=10;
        a.l++;
    }
    return a;
}

int main(){
    //首先这个n很小,题目给的内存很大,用高精度*单精度写一发(并且此题只要求输出最右边的数)
    c[0].s[0]=1;
    c[0].l=1;
    for(int i=1;i<=100;i++)
        c[i]=c[i-1]*i;
    int n;
    scanf("%d",&n);
    for(int i=0;i<c[n].l;i++){
        if(c[n].s[i]!=0){
            printf("%d\n",c[n].s[i]);
            break;
        }
    }
    return 0;
}

算法训练 最大最小公倍数(贪心)

在这里插入图片描述
  容易想到的就是n·(n-1)·(n-2)/gcd(n,n-2)和n·(n-1)·(n-3)/gcd(n,n-3),一开始想到的是,n为奇数的时候一定是第一种,为偶数的时候就是第二种情况.但是此时我们只能通过60%的数据,我们还可以发现n是偶数的时候,n和n-3可能还有公因子,那么此时就要和(n-1)·(n-2)·(n-3)再次比较因为这三个数是没有公因子的.

LL gcd(LL a,LL b){
	return b==0?a:gcd(b,a%b);
}
int main(){  
	LL n;
	scanf("%lld",&n);
	if(n==1) printf("1\n");
	else if(n==2) printf("2\n");
	else {
		LL ans=max(max(n*(n-1)*(n-2)/gcd(n,n-2),n*(n-1)*(n-3)/gcd(n,n-3)),(n-1)*(n-2)*(n-3)/gcd(n-1,n-3));
		printf("%lld\n",ans);
	}
    return 0;
}

算法训练 关联矩阵(基础概念)

关联矩阵是描述点与边的关系

int main(){  
	int n,m;
	scanf("%d%d",&n,&m);
	rep(i,1,m){
		int x,y;
		scanf("%d%d",&x,&y);
		a[x][i]=1;
		a[y][i]=-1;
	}
	rep(i,1,n)
		rep(j,1,m)
			printf("%d%c",a[i][j],j==m?'\n':' ');
    return 0;
}

算法训练 Torry的困惑(基本型) (素数筛)

在这里插入图片描述

void get_prime(){
	rep(i,2,Max_n) is_prime[i]=true;
	rep(i,2,sqrt(Max_n)){
		if(is_prime[i]){
			for(int j=i*i;j<=Max_n;j+=i)
				is_prime[j]=false;
		}
	}
	num=1;
	rep(i,1,Max_n)
		if(is_prime[i])
			prime[num++]=i; 
}

int main(){  
	get_prime();
	int n; sc(n);
	LL ans=1;
	rep(i,1,n) ans=(ans*prime[i])%mod;
	printf("%lld\n",ans);
    return 0;
}

算法训练 字串统计(STL map,string的应用)

这个代码写的有点乱(我自己都有点乱了?)(水过一把),回来在更新一个思路比较清晰的,STL的应用参考我的ACM_STL应用专题的STL专题总结.

#include<cstdio>
#include<cstring>
#include<cmath> 
#include<map>
#include<algorithm> 
#include<iostream>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define sc(n) scanf("%d",&n);
#define me(a) memset(a,0,sizeof(a));
#define mod 50000
using namespace std;
 
const int Max_n=100005;
typedef long long LL;

int main(){  
	int k,mmax=-1;
	string a,b;
	cin>>k>>a;
	map<string,int>m;
	map<string,int>index;
	int n=a.length();
	int num=0,index1=-1,mmaxlen=-1;
	for(int len=k;len<n;len++){
		for(int l=0;l+len-1<n;l++){
			m[a.substr(l,len)]++; 
			index.insert(make_pair(a.substr(l,len),++num));
			if(m[a.substr(l,len)]>mmax){//找到出现次数最大的 
				b=a.substr(l,len);
				index1=num;
				mmax=m[a.substr(l,len)];
				mmaxlen=len;
			}
			if(m[a.substr(l,len)]==mmax&&index[a.substr(l,len)]<index1){//找到出现最早的 
				b=a.substr(l,len);
				index1=index[a.substr(l,len)];
				mmaxlen=len;
			}
			if(m[a.substr(l,len)]==mmax&&len>mmaxlen){//找到最长的 
				b=a.substr(l,len);
				index1=index[a.substr(l,len)]; 
				mmaxlen=len;
			} 
		}
	}
	cout<<b<<endl;
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值