目录
一、学习知识
1、欧拉筛法
2、大数(+、-、*)
3、队列
4、桶排
5、埃式筛法
7、栈
8、快速幂
9、BFS(重点)
二、刷题(本周刷有25题:选其中几个)
1、1687 H 骨牌铺方格2
2、1686 E 智兵点将
3、1686 D 实验室的聚餐
4、1684 J 字符串操作一(串)
5、1685 B YRZ学长的随机数
分析(1)、计算1到n之间的素数
(2)、用一数组a(全赋值1默认全素数)记录1到n之间的状态,用一数组b装素数
(3)、1级大循环开始时检测从2开始时 a[i]状态是1还是0,是1 b[m++]=a[i];接下来2级小循环j=0开始将 b中素数给*i 即 a[i*b[j]]=0;改变(素数倍数一定不是素数)记录状态,注意循环范围
(4)、最后输出 b中元素
附代码
- #include
- #include
- int main(int argc, char *argv[])
- { int n,flig[1000],i,j,sux=0;;
- while(scanf("%d",&n)!=EOF)
- {sux=0;
- int su[1000];
- memset(flig,1,sizeof(flig));
- for(i=2;i<=n;i++)
- {if(flig[i])
- su[sux++]=i;
- for(j=0;i*su[j]<=n;j++)
- {flig[i*su[j]]=0;
- if(i%su[j]==0)break;
- }
- }
- for(i=0;i
- printf("%d\n",su[i]);
- }
- return 0;
- }
分析(1)、进行很大的数之间的数学运算
(2)、将我们输入的数存入字符串中后在赋给整形数组,并右对齐
(3)、通过循环从右往左对位检测,按照数学计算方式,计算
附代码(大数 (加) 其他概念一样 就数学实现方式不一样)
- #include
- #include
- int main()
- { int sa[100]={0},sb[100]={0},js[100]={0},i,j;
- int ac=0,bc=0,zz,duo=0;
- char a[100],b[100];
- gets(a);gets(b);
- ac=strlen(a);bc=strlen(b);
- for(i=100-ac,j=0;i<100;i++)
- sa[i]=a[j++]-'0';
- for(i=100-bc,j=0;i<100;i++)
- sb[i]=b[j++]-'0';
- if(ac>bc)zz=ac;
- else if(bc>ac)zz=bc;
- else zz=ac;
- for(i=99;zz>0;i--,zz--)
- {js[i]=(sa[i]+sb[i]+duo)%10;
- duo=(sa[i]+sb[i]+duo)/10;
- if(zz-1<=0&&duo!=0){js[--i]+=duo;}
- }
- for(i=i+1;i<100;i++)
- printf("%d",js[i]);
- return 0;
- }
分析(1)、先进先出,一端进行插入(入队列 队尾),另一端进行删除(出队列 队首)
(2)、实现 运用链表结构或数组
附代码(函数实现)
- typedef struct {
- int arr[SIZE];
- int head;
- int tail;
- }queue;
- void queue_init(queue *queue) {
- queue->head = 0;
- queue->tail = 0;
- }
- void deinit(queue *queue) {
- queue->head = 0;
- }
- int size(const queue *queue) {
- return (queue->tail - queue->head);
- }
- int empty(const queue *queue) {
- return !(queue->tail - queue->head);
- }
- int full(const queue *queue) {
- return queue->tail >= SIZE;
- }
- int push(queue *queue, int val) {
- if(queue_full(queue)) {
- return 0;
- }
- else {
- queue->arr[queue->tail] = val;
- queue->tail++;
- return 1;
- }
- }
- int pop(queue *queue, int *num) {
- if(queue_empty(queue)) {
- return 0;
- }
- else {
- *num =queue->arr[queue->head];/
- queue->head++;
- return 1;
- }
- }
- int front(const queue *queue, int *num) {
- if(enpty(queue)) {
- return 0;
- }
- else {
- *num = queue->arr[queue->head];
- return 1;
- }
- }
分析(1)、按照函数映射方法将不同的数据放入不同的桶中
(2)、将每个桶内排好序,在依次取出桶中数据
附代码
- #include
- #include
- typedef struct fw
- {int a;
- struct fw *next;
- }tp;
- int main(int argc, char *argv[])
- { int a[10],i,j,index;
- tp **to,*p,*q,*s;
- for(i=0;i<10;i++)scanf("%d",&a[i]);
- to=(tp**)malloc(sizeof(tp*)*10);
- for(i=0;i<10;i++)
- {to[i]=(tp*)malloc(sizeof(tp));
- to[i]->a=-1;
- to[i]->next=NULL;
- }
- for(i=0;i<10;i++)
- { s=(tp*)malloc(sizeof(tp));
- s->next=NULL;
- s->a=a[i];
- index=a[i]/100;
- p=to[index];q=p->next;
- if(to[index]->a==-1)to[index]=s;
- else if(s->a
a){to[index]=s;s->next=p;} - else {while(q&&s->a>q->a){p=q;q=q->next;}p->next=s;s->next=q;}
- }
- for(i=0;i<10;i++)
- if(to[i]->a==-1)continue;
- else {p=to[i];while(p){printf("%d ",p->a);p=p->next;}}
- return 0;
- }
分析(1)、算1-n之间素数
(2)、用一数组a装1-n之间的数,循环从i=2开始到i<=sqrt,在小循环i<=n将i的倍数a[i]=0,依次循环,知道结束
(3)、输出时判断a每个元素的状态为0就不输出,其他就是素数
附代码
- #include
- #include
- #include
- int main(int argc, char *argv[])
- {
- int n,*a,i,j=0;
- scanf("%d",&n);
- a=(int*)malloc(sizeof(int)*(n+1));
- a[0]=0;
- for(i=1;i<=n;i++)a[i]=i;
- for(i=2;i<=sqrt(n);i++)
- for(j=i;j<=n;j=j+i)
- {if(j!=i)a[j]=0;}
- for(i=2;i<=n;i++)
- if(a[i]!=0)printf("%d ",a[i]);
- return 0;
- }
6、归并排
分析(1)、运用递归,将数组分成左右两部分,依次递归下去,直到只剩2个不能分了,
(2)、在通过递归进行从下往上的合并并排序
- #include
- void shuchu(int a[], int b) {
- int i;
- for (i=0;i
- printf("%d ", a[i]);
- }
- }
- void pai(int arr[], int start, int z, int end) {
- int zhang[20];
- int k = 0;
- int i = start;
- int j = z + 1;
- while (i <= z && j <= end) {
- if (arr[i] < arr[j]){
- zhang[k++] = arr[i++];
- }
- else{
- zhang[k++] = arr[j++];
- }
- }
- if (i == z + 1) {
- while(j <= end)
- zhang[k++] = arr[j++];
- }
- if (j == end + 1) {
- while (i <= z)
- zhang[k++] = arr[i++];
- }
- for (j = 0, i = start ; j < k; i++, j++) {
- arr[i] = zhang[j];
- }
- }
- void gui(int a[], int start, int end) {
- if (start >= end)
- return;
- int z = ( start + end ) / 2;
- gui(a, start, z);gui(a, z + 1, end);
- pai(a, start, z, end);
- }
- int main()
- {
- int a[] = {9, 8, 1, 3, 5, 1, 7, 2, 4, 6};
- gui(a, 0, 9);
- shuchu(a, 10);
- return 0;
- }
分析(1)、运用结构体 先进后出
(2)、注意创建栈 入栈 出栈
附代码
- #include
- #include
- #include
- typedef struct{
- char data[100];
- int to;
- int di;
- }stack;
- stack *cj()
- {
- stack *p=(stack*)malloc(sizeof(stack));
- p->di=p->to=0;
- return p;
- }
- void jr(stack *p,char str){
- p->data[p->to]=str;
- p->to++;
- }
- char chuzhan(stack *p,char str){
- if(p->to!=p->di){
- str=p->data[p->to-1];
- p->to--;
- return str;
- }
- }
- void shuchu(stack *p){
- while(p->to!=p->di){
- printf("%c",p->data[p->to-1]);
- p->to--;
- }
- }
- int main(){
- int i;
- stack *p;
- char a[100];
- gets(a);
- p=cj();
- for(i=0;i
- jr(p,a[i]);
- printf("\n");
- shuchu(p);
- }
分析(1) 、通过循环检测次方状态(a^b) 偶数 b次方折半 底数a自己*自己 奇数时用另一个变量b
接收即b*=a 次方时负数时 b/=a 就相到与 把次方是奇数时 底数提出一个 次方减了个一 变成偶数了 ,在折半,知道b=1;
附代码
- #include
- #include
- float pow(float a,int b)
- { float ans=1;
- while(b)
- {if(b&1)
- {if(b>0)
- ans*=a;
- else ans/=a;
- }
- b=b/2;
- a*=a;
- }
- return ans;
- }
- int main(int argc, char *argv[])
- { float a;
- int b;
- scanf("%f%d",&a,&b);
- printf("%f",pow(a,b));
- return 0;
- }
分析(1)、要运用队列和结构体
(2)、先给队首赋根节点
(3)、找可拓展点入队 如果没有了就将队首出队
(4)、要定义对下标数组记录已找过的点
(5)、重复(3)没有可拓展或已找到停止
附代码
- #include
- #include
- typedef struct bfs
- {int a;
- int b;
- }dui;
- queue
r; - int dx[4]={0,1,0,-1};
- int dy[4]={1,0,-1,0};
- int k1,k2,n;
- char a[100][100];
- int v[100][100]={0};
- int main()
- { int i,w1,w2;
- while(scanf("%d",&n)!=EOF)
- {int k=0;
- getchar();
- for(i=0;i
- {gets(a[i]);}
- scanf("%d%d%d%d",&w1,&w2,&k1,&k2);
- dui to;
- to.a=w1;
- to.b=w2;
- r.push(to);
- v[w1][w2]=1;
- while(!r.empty())
- {int x=r.front().a,y=r.front().b;
- if(x==k1&&y==k2)
- {printf("Yes\n");k=1;break;}
- int i;
- for(i=0;i<=3;i++)
- {int tx,ty;
- tx=x+dx[i];
- ty=y+dy[i];
- if(a[tx][ty]!='*'&&v[tx][ty]==0&&tx>=0&&tx
=0&&ty - {dui temp;
- temp.a=tx;
- temp.b=ty;
- r.push(temp);
- v[tx][ty]=1;
- }
- }
- r.pop();
- }
- if(k==0)printf("No\n");
- }
- return 0;
- }
题解(1)先给定1、2、3定值从第4个开始等于前3个相加。
#include
int
main()
{
int
n;
while
(
scanf
(
"%d"
,&n)!=EOF)
{
long
long
a[100]={0};
int
i=n;
a[1]=1;a[2]=2;a[3]=4;
if
(i>3)
for
(i=4;i<=n;i++)
{a[i]=a[i-1]+a[i-2]+a[i-3];}
printf
(
"%lld\n"
,a[i>3?i-1:i]);
}
return
0;
}
题解(2)以7的倍数为基准 加上用户输入最终%7的余数 %3和5 等于 用户输入最终的%3 和5的余数时 停止循环 输出此时 7的倍数加上用户输入最终%7的余数
- #include
- int main(int argc, char *argv[])
- { int a,b,c,i,j=1,k;
- scanf("%d%d%d",&a,&b,&c);
- while(1)
- {k=7*(j++);
- if((k+c)%5==b&&(k+c)%3==a)break;
- }
- printf("%d",k+c);
- return 0;
- }
题解(3)用一维数组记录醉酒状态,全赋1(表示初始状态都没醉)用一变量记录报数状态,用一变量记录人数好让数组到最后一人时返回开头,报道最后数的人赋0(醉),此时下一个人报数值归1;当检测到当前人时0,就跳过,下一个人往后报,当记录醉酒人数的变量加到男生的人数时,结束循环,最后输出时检测数组状态0就输出B,1就输出G。
#include
#include
#include
int
main()
{
int
n,m,i,z=0,j=0,h=0,a[10000],k;
char
x;
while
((x=
scanf
(
"%d%d"
,&n,&m))!=EOF)
{
memset
(a,1,
sizeof
(
int
)*10000);
i=0;z=n;j=0;
while
(z>0)
{
if
(a[i]!=0)j++;
if
(j==m){a[i]=0;z--;j=0;}
i++;
if
(i>=2*n)i=0;
}
for
(i=1;i<=2*n;i++)
{
if
(a[i-1]==0)
putchar
(
'B'
);
else
putchar
(
'G'
);
if
(i%50==0)
printf
(
"\n"
);
}
printf
(
"\n\n"
);
}
return
0;
}
题解(4)将字符串分成左右两部分分别左右交换
- #include
- #include
- void jh(char a[100],int m,int n)
- {int i,j,ac;
- char c;
- ac=strlen(a);
- for(i=0,j=ac-1;i<=m&&j>=n;i++,m--,j--,n++)
- {c=a[i];a[i]=a[m];a[m]=c;
- c=a[j];a[j]=a[n];a[n]=c;
- }
- puts(a);
- }
- int main(int argc, char *argv[])
- { char a[100];
- while(scanf("%s",&a)!=EOF)
- {int i,j;
- if(strlen(a)%2==0)
- {i=strlen(a)/2-1;
- j=strlen(a)/2;
- jh(a,i,j);
- }
- else
- {i=strlen(a)/2-1;
- j=strlen(a)/2+1;
- jh(a,i,j);
- }
- }
- return 0;
- }
题解(5)用数字记录随机数,当用户输入随机数时,就在数组内检测是否重复,没重复就将此数在数组内排序。
- #include
- int main()
- { int N,num[100]={0},i,j,k,m;
- scanf("%d",&N);
- for(i=0;i
- scanf("%d",&num[i]);
- for(i=0;i
- {k=i;
- for(j=i;j
- if(num[k]>num[j])
- k=j;
- if(k!=i)
- {m=num[i];
- num[i]=num[k];
- num[k]=m;
- }
- }
- for(i=0;i
- {k=i;
- if(num[k]==num[i+1])
- { for(k;k
- num[k]=num[k+1];
- N--;i--;
- }}
- printf("%d\n",N);
- for(i=0;i
- printf("%d ",num[i]);
- return 0;
- }