zoukankan      html  css  js  c++  java
  • 算法竞赛入门经典 第3章 数组和字符串 学习笔记 1

    算法竞赛入门经典 第3章 数组和字符串 学习笔记

    第一篇

    数组

    逆序输出

    #include<iostream>
    using namespace std;
    #define maxn 105 //在算法竞赛中,常常难以精确计算出需要的数组大小,数组一般会声明得稍 大一些。在空间够用的前提下,浪费一点不会有太大影响。
    int a[maxn];
    int main()
    {
    	int x;
    	int n=0;
    	while(cin>>x)
    	{
    		a[n++]=x;   //a[n++]=x,它做了两件事:首先赋值a[n]=x,然后执行n=n+1。	
    	}
    	for(int i=n-1;i>=1;i--)
    	{
    		cout<<a[i]<<" ";
    	}
    	cout<<a[0]<<endl;
    	return 0;
    } 
    

    对比一下这段代码

    #include<iostream>
    using namespace std;
    #define maxn 100000000000
    int main()
    {
    	int x;
    	int n=0;
    	int a[maxn]; //异常退出了 
    	while(cin>>x)
    	{
    		a[n++]=x;   	
    	}
    	for(int i=n-1;i>=1;i--)
    	{
    		cout<<a[i]<<" ";
    	}
    	cout<<a[0]<<endl;
    	return 0;
    } 
    

    比较大的数组应尽量声明在main函数外,否则程序可能无法运行
    如果声明的是“int a[maxn],b[maxn]”,是不能赋值b=a的。
    如果要从数组a复 制k个元素到数组b,可以这样做:memcpy(b,a,sizeof(int)k)。
    当然,如果数组a和b 都是浮点型的,复制时要写成“memcpy(b,a,sizeof(double)
    k)”。
    另外需要注意的是, 使用memcpy函数要包含头文件string.h。
    如果需要把数组a全部复制到数组b中,可以写得简单 一些:memcpy(b,a,sizeof(a))

    #include<iostream>
    #include<cstring>
    using namespace std;
    int main()
    {
    	int a[5]={1,2,3,4,5};
    	int b[5];
    	//从数组a复制k个元素到数组b
    	memcpy(b,a,sizeof(int)*3);
    	for(int i=0;i<3;i++)
    	cout<<b[i]<<" ";
    	return 0;
    }
    

    开灯问题,很有趣
    开灯问题。有n盏灯,编号为1~n。第1个人把所有灯打开,第2个人按下所有编号为2 的倍数的开关(这些灯将被关掉),第3个人按下所有编号为3的倍数的开关(其中关掉的灯 将被打开,开着的灯将被关闭),依此类推。一共有k个人,问最后有哪些灯开着?
    输 入n和k,输出开着的灯的编号。k≤n≤1000。
    样例输入: 7 3
    样例输出: 1 5 6 7
    【分析】用a[1],a[2],…,a[n]表示编号为1,2,3,…,n的灯是否开着。模拟这些操作即可。
    注:代码里还控制让行末不输出空格
    先贴书里给的代码:

    #include<iostream>
    #include<cstring>   //memset头文件
    #define maxn 1010
    using namespace std;
    int a[maxn];
    int main()
    {
    	int n,k,first=1;
    	memset(a,0,sizeof(a));
    	cin>>n>>k;
    	for(int i=1;i<=k;i++) //人
    	{
    		for(int j=1;j<=n;j++) //灯
    		{
    			if(j%i==0) a[j]=!a[j];          //灯是人的倍数
    		} 
    	}
    	for(int i=1;i<=n;i++)
    	{
    		if(a[i])
    		{
    			if(first)
    			first=0;
    			else
    			cout<<" ";
    			cout<<i;
    		}
    	}
    	cout<<endl;
    	return 0;
    } 
    
    

    事实上,控制行末不输出空格,就是让空格在每一个数前面输出,第一个数最前面不输出空格,以后的数每个都是先输出空格再输出a[i]
    “memset(a,0,sizeof(a))”的作用是把数组a清零,它也在string.h中定义。
    虽然也能用for循环完成相同的任务,但是用memset又方便又快捷。
    另一个技巧在输出:为了避免输出 多余空格,设置了一个标志变量first,可以表示当前要输出的变量是否为第一个。第一个变 量前不应有空格,但其他变量都有。
    自己设计的:

    #include<iostream>
    using namespace std;
    int main()
    {
    	int n,k;
    	cin>>n>>k;
    	int a[n]={0};
    	//第一个人把所有的灯都打开了,就相当于是改变了所有1的倍数的灯的状态
    	for(int i=1;i<=k;i++)
    	{
    		for(int j=1;i*j<=n;j++)
    		{
    			a[i*j]=!a[i*j];      //改变状态,用a[j]=!a[j]
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		if(a[i]==1) cout<<i<<" ";
    	} 
    	return 0;
    }
    
  • 相关阅读:
    LIS例题
    基数排序板子
    lower_bound和upper_bound在刷leetcode的时候...
    leetcode1081/316 求字典序最小的包含所有出现字符一次的子序列
    PHP 求多个数组的笛卡尔积,适用于求商品规格组合 【深度优先搜索】【原创】
    PHP 求多个数组的笛卡尔积,适用于求商品规格组合【原创】
    Spring 中注入 properties 中的值
    Java 枚举活用
    Intellij IDEA 快捷键整理(TonyCody)
    WIN API -- 2.Hello World
  • 原文地址:https://www.cnblogs.com/serendipity-my/p/12632955.html
Copyright © 2011-2022 走看看