CSDN每日一练20230227(去除整数)

题目名称:奇偶排序

题目描述

给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数。(测试用例仅做参考,我们会根据代码质量进行评分)

输入描述:

第一行输入整数n。(1<=n<=1000)表示数组大小 第二行输入n个整数a.(1<=n<=100)

输出描述:

输出重排之后的数组。

示例

输入
6
3 34 67 89 90 58
输出
3 67 89 34 90 58

如果用冒泡那就慢了。
我这里用了内置qsort函数
规则:奇数在前,偶数在后,其余情况保持不变
更多qsort使用技巧见算法学习之路4 qsort的使用,让问题简单化

#include <stdio.h>
#include <stdlib.h>
int cmp(const void*pa,const void*pb) {
	int a=*((int*)pa);
	int b=*((int*)pb);
	//相等就不交换
	if(a%2==b%2) {
		//return a>b;
		return 0;
	} else {
		//偶数放后面
		return a%2<b%2;
	}
}
void solution(int n, int arr []) {
	// TODO: 请在此编写代码
	qsort(arr,n,sizeof(int),cmp);
	for (int i=0;i<n;i++) {
		printf("%d ",arr[i]);
	}
}
int main() {
	int n;
	scanf("%d", &n);
	int* arr;
	arr = (int*)malloc(n * sizeof(int));
	for (int i = 0; i < n; i++) {
		scanf("%d", &arr[i]);
	}
	solution(n, arr);
	return 0;
}

题目名称:争风吃醋的豚鼠

题目描述

N个节点两两建边。 不存在3个节点相互之前全部相连。(3个节点连接成环) 最多能建立多少条边?

输入描述:

输入整数n.(1<=n<=1e5)

输出描述:

输出最大边数

示例

输入 4
输出 4

将数据分成2组数据相乘即可,同组内所有数据都与另一组相连可能最大数,同组内不可相连。
说明:由于A1跟A2都与BX相连,则A1跟A2相连就会有闭环A1A2BX
4个点时 A1 B1 A2 B2有
A1->B1 A1->B2
A2->B1 A2->B2
共4条
5个点时 A1 B1 A2 B2 A3有
A1->B1 A1->B2
A2->B1 A2->B2
A3->B1 A3->B2
共6条

#include <stdio.h>
#include <stdlib.h>
void solution(int n) {
	int a=n/2;
	int b=n-a;
	printf("%d",a*b);
}
int main() {
	int n;
	scanf("%d", &n);
	solution(n);
	return 0;
}

题目名称:去除整数

题目描述

已知存在集合A包含n个整数,从1到n。 存在m个整数a[1…m]。 在集合A中去除这m个整数的的倍数。 输出集合中包含的元素的个数。

输入描述:

第一行输入n,m。(1<=n<=1e9,1<=m<=10) 第二行输入m个32位整数。

输出描述:

输出集合中包含元素的个数。

示例

输入
5 2
2 3
输出
2

计算公式是有的,正常m如果是3个,我们手动就能计算出来
这里直接引用这里的文章
https://blog.csdn.net/qq_30277239/article/details/127400788

n = 100,m = 3,a = [2, 3, 4]。100以内能被2整除的有50个,能被3整除的有33个,能被4整除的有25个,能否说明能被2或者3或者4整除的一共有50 + 33 + 25 = 108个呢?显然是不能的。设能被2整除的有x个,被3整除的有y个,被4整除的有z个,能被2和3整除的有a个,能被2和4整除的有b个,能被3和4整除的有c个,能被2,3,4整除的有d个,根据容斥原理可得,能被2或者3或者4整除的一共有x + y + z - a - b - c + d个。
公式是res = x1 - x2 + x3 - x4 +…个

知道计算公式也就不难了。
剩下的就是复杂的计算,要依次从当中挑x个,过程比较繁琐
涉及到排序,求最大公约数
综合性比较强
当然这么做就繁琐了,写代码也要很长时间
比较简单的就是对n个数设置标识位
对m个数进行遍历,如果未标识,则总数-1,并标识,如果已标识则跳过
需要比较数为n/m1+n/m2…,比起n*m的方法(这里还有除法)肯定要少的多
如m1=2,2,4,6,8,10,12…被标识总数并减少
m2=3时,由于6,12已被标识,则不会重复减。
一开始用的是int数组来标识,通过率只有80%,发现是段错误了。
换成char数组,通过率100%

比较简单的方式

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
//用char申请空间可全过
void solution(int n, int m, int arr[]) {
	int count=n;
	char *flag=(char*)malloc(sizeof(char)*(n+1));
	memset(flag,0,sizeof(char)*(n+1));
	//int 会断错误
	//int *flag=(char*)malloc(sizeof(int)*(n+1));
	//memset(flag,0,sizeof(int)*(n+1));
	for (int i=0;i<m;i++) {
		int check=arr[i];
		for (int j=check;j<=n;j+=check) {
			if(flag[j]==0) {
				flag[j]=1;
				count--;
			}
		}
	}
	printf("%d",count);
}
int main() {
	int tem_arr[2];
	for (int i = 0; i < 2; i++) {
		scanf("%d", &tem_arr[i]);
	}
	int n = tem_arr[0];
	int m = tem_arr[1];
	int* arr;
	arr = (int*)malloc(m * sizeof(int));
	for (int i = 0; i < m; i++) {
		scanf("%d", &arr[i]);
	}
	solution(n, m, arr);
	return 0;
}

基于概念的方式

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
//最大公约数
int gys(int a,int b) {
	if(a<b) {
		int c=a;
		a=b;
		b=c;
	}
	while(a%b!=0) {
		int c=a%b;
		a=b;
		b=c;
	}
	return b;
}
//最小公倍数
int64_t gbs(int a,int b) {
	return (int64_t)a*b/gys(a,b);
}
void showarr(int arr[],int m) {
	for (int i=0;i<m;i++) {
		printf("%d ",arr[i]);
	}
	printf("\n");
}
void swap(int arr[],int a,int b) {
	int c=arr[a];
	arr[a]=arr[b];
	arr[b]=c;
}
int g_n=0;
int ret[20]= {
	0
}
;
void countnum(int arr[],int step) {
	int64_t mingbs=arr[0];
	for (int i=1;i<step;i++) {
		mingbs=gbs(mingbs,arr[i]);
	}
	//showarr(arr,step);
	//printf("mingbs %d\n",mingbs);
	ret[step]+=g_n/mingbs;
}
void sortarray(int m, int arr[],int pos,int step) {
	if(pos==step) {
		countnum(arr,step);
		return;
	}
	for (int i=pos;i<m;i++) {
		//要比前一个大
		if(pos>0 && arr[pos-1]>arr[i]) {
			continue;
		}
		swap(arr,i,pos);
		sortarray(m,arr,pos+1,step);
		swap(arr,i,pos);
	}
}
void solutionv2(int n, int m, int arr[]) {
	g_n=n;
	for (int i=1;i<=m;i++) {
		sortarray(m,arr,0,i);
	}
	int delnum=0;
	for (int i=1;i<=m;i++) {
		if(i%2==1) {
			delnum+=ret[i];
		} else {
			delnum-=ret[i];
		}
	}
	printf("%d",n-delnum);
}

int main() {
	int tem_arr[2];
	for (int i = 0; i < 2; i++) {
		scanf("%d", &tem_arr[i]);
	}
	int n = tem_arr[0];
	int m = tem_arr[1];
	int* arr;
	arr = (int*)malloc(m * sizeof(int));
	for (int i = 0; i < m; i++) {
		scanf("%d", &arr[i]);
	}
	solutionv2(n, m, arr);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值