前言
洛谷入门题目知识点整理和一些基础知识点
一、基础知识巩固
1 结构体
定义一个结构体:
strunct man
{
char name[10];
int age;
}
eg:
#include<stdio.h>
struct man
{
char name[10];
int age;
};
int main()
{
struct man wjc;
wjc.name[0]='z';
wjc.age=1000;
printf("%s %d",wjc.name,wjc.age);
}
2 递归
//10的阶乘
#include<stdio.h>
int mul(int x)
{
return x==1? 1 : x*mul(x-1); //套娃行为
}
int main()
{
printf("%d",mul(10));
}
3 最多保留两位小数
double类型,如果是整数则不用输出小数部分,如果是一位小数则输出一位,否则输入两位小数。
如何实现:
if (floor(ans)==ans){
printf("%d",ans) ;
}//说明ans没有小数位,直接用整数方法输出
else if (floor(ans*10)==ans*10){
printf("%.1f",ans);
}//说明ans小数点向右移动一位后就没有小数了,说明是一位小数
printf("%.2f",ans);//否则小数位大于等于2,直接%.2f输出
4.memset函数
多用于清空数组,对一段内存空间全部设置为某个字符(一般为0,1或-1),原型是
memset(butter,0,sizeof(buffer))
eg: char a[10];memset(a,1,10);
头文件是…是啥来着,我查查
#include<string.h>
误区:memset的内部实现是以字节为单位进行赋值的,如果是int 类型则大于一个字节,会报错。
二、对角线求结点
题目:对于一个 n 个顶点的凸多边形,它的任何三条对角线都不会交于一点。请求出图形中对角线交点的个数。对于 50%的数据,保证3≤n≤100.对于100%的数据,保证3≤n≤10e5.
1.分析
从对角线和结点的关系入手,可分析出结点一定为两条对角线相交所得,不存在三条或多条对角线相交得一个结点的情况。
再从多边形顶点和对角线的关系入手,两条对角线可以确定四个顶点,反推每四个顶点组合就能确定两条对角线和一个结点。所以只需求出该多边形有几种四个顶点组合就能确定出有几个结点。
2. 源代码
#include<stdio.h>
int main()
{
unsigned long long n,a;
scanf("%lld",&n);
if(n<=3)
{
printf("0");
}
else{
a=n*(n-1)/2*(n-2)/3*(n-3)/4;//防止爆掉
printf("%lld",a);
}
return 0;
}
三、质数筛
1.暴力法的优化
暴力法:直接从2到n遍历看是否能整除,但可以分析出只需要取到sqrt(n)即可,因为两个因数必定在sqrt(n)的两侧
承接题目:输入 n(n≤100) 个不大于 100000 的整数。要求全部储存在数组中,去除掉不是质数的数字,依次输出剩余的质数。
bool isPrime_1( int num )
{
int i;
if(num<=1)return false;
for(i=2;i<=sqrt(num);i++)
{
if(num%i==0) return false;
}
return true;
if(num==2||num==3) return true;
}
源代码:
#include<stdio.h>
#include<math.h>
#include<stdbool.h>
bool Isprime (int num)
{
int i;
if(num<=1)return false;
for(i=2;i<=sqrt(num);i++)
{
if(num%i==0) return false;
}
return true;
if(num==2||num==3) return true;
}
int main()
{
int n;
int j;
int b[100];
scanf("%d",&n);
for(j=0;j<n;j++)
{
scanf("%d",&b[j]);
}
for(j=0;j<n;j++)
{
if(Isprime(b[j]))
{
printf("%d ",b[j]);
}
}
return 0 ;
}
2.步长为6的优化
令x>=1的话,可以将大于5的自然数表示为
······ 6x-1,6x,6x+1,6x+2,6x+3,6x+4,6x+5,6(x+1),6(x+1)+1 ······
可以看到有一个循环6x-1,6x,6x+1,6x+2,6x+3,6x+4
不难知道不在6x左右两侧的数一定不是质数,但在两侧的数也不一定都是质数,所以删掉不在两侧的数,只对两侧的数判断是否为质数就好。
bool Isprime(int n)
{
if (n==1) return false;
if (n==2||n==3) return ture;
if(n%6!=1&&n%6!=5) return false;//判断不在两侧
for(i=5;i*i<=n;i+=6){
if(n%i==0||n%(i+2)==0) return false;
return true; }
}
emmm…
3.埃氏筛
看了一些解释我理解的是所有合数都可以由素数乘素数得来,所以只要将已知素数作为因数做乘法,删除所得数(合数)即可。
源代码:
//埃氏筛法
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#include <string.h>
bool num[101];
int i,j,n;
int main()
{
memset (num,1,sizeof(num));
scanf("%d",&n);
for (i=2;i<=sqrt(n);i++)
{
if(num[i])
{
for(j=i*i;j<=n;j+=i)//筛去合数
num[j]=0;
}
}
for(i=2;i<=n;i++)
{
if(num[i])
printf("%d ",i);
}
return 0;
}
3.(线性筛)欧拉筛
还没有弄明白,之后补上orz