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;
    }
    
  • 相关阅读:
    广义后缀自动机模板
    HDU 5852 Intersection is not allowed! ( 2016多校9、不相交路径的方案、LGV定理、行列式计算 )
    BZOJ 4017 小 Q 的无敌异或 ( 树状数组、区间异或和、区间异或和之和、按位计贡献思想 )
    WHU 583 Palindrome ( 回文自动机 && 本质不同的回文串的个数 )
    HDU 5527 Too Rich ( 15长春区域赛 A 、可贪心的凑硬币问题 )
    HDU 5863 cjj's string game ( 16年多校10 G 题、矩阵快速幂优化线性递推DP )
    HDU 5544 Ba Gua Zhen ( 2015 CCPC 南阳 C、DFS+时间戳搜独立回路、线性基 )
    HDU 5734 Acperience ( 数学公式推导、一元二次方程 )
    hihocoder 1251 Today is a rainy day ( 15年北京 C、暴力 )
    HDU 5113 Black And White ( 2014 北京区预赛 B 、搜索 + 剪枝 )
  • 原文地址:https://www.cnblogs.com/serendipity-my/p/12632955.html
Copyright © 2011-2022 走看看