学大伟业 Day 1 培训总结
第一天培训,讲的基本算法,东西很多。还有些数论,图论,数据结构and some small tricks
一.输入输出技巧
1 //输入输出技巧 2 /* 3 scanf、printf:速度快,需要记忆不同数据类型的格式化字符串 4 cin、cout:简单,在某些情况下较慢 5 getchar:读入一个字符 6 puts/gets/cin.getline(a,100)如果a是大小为100的字符数组/getline(cin,a)如果a是一个string:输出/输入一个字符串 7 */ 8 #include<iostream> 9 #include<cstdio> 10 #include<cstring> 11 #include<algorithm> 12 using namespace std; 13 int main() 14 { int a,n,h,min; 15 char m[3]; 16 // 1.题目中不清楚输入输出的数据数量,可以用scanf的返回值解决。 17 while(scanf("%d",&a)!=EOF) 18 { 19 n++; 20 //..... 21 } 22 // 2.cin读入字符串以空格、回车结束。scanf、getchar读入字符串不会舍弃回车。gets读入字符串以回车结束。 23 std::ios::sync_with_stdio(false);//cin可以关闭同步加速。 24 25 // 3.scanf的妙用。举个栗子。再输入一个时间的时候,往往用字符串读入再取出时间。但scanf可以直接取出时间。 26 scanf("%d:%d",&h,&min);//当在读入时必须遇到‘:’才会继续读入,读入的为两个整数,就是时间。 27 }
二.数组的高级用法
1 //基础数据结构——数组 2 /* 3 数组很常见,同时也是很多高级数据结构的基础 4 数组也有很多妙用 5 6 基本:储存数据,做统计等 7 扩展:部分和数组,差分数组 8 */ 9 #include<iostream> 10 #include<cstdio> 11 #include<algorithm> 12 #include<cstring> 13 using namespace std; 14 int a[100]; 15 int sum[100];//部分和(前缀和)数组 sum[i]表示 a[i]+a[2]+...+a[i] 的值 16 int diff[100];//差分数组 17 int sumd[100];//差分数组diff的部分和数组 18 int main() 19 { 20 int n; 21 scanf("%d",&n); 22 for(int i=1;i<=n;i++) 23 scanf("%d",&a[i]); 24 25 //sum : 26 sum[1]=a[1]; 27 for(int i=2;i<=n;i++) 28 sum[i]=sum[i-1]+a[i]; 29 //用途:方便计算区间 L~R 的值num 30 int L,R; 31 scanf("%d%d",&L,&R); 32 int num=sum[R]-sum[L-1]; 33 34 //diff : 35 diff[1]=a[1]; 36 for(int i=2;i<=n;i++) 37 diff[i]=a[i]-a[i-1]; 38 //用途:差分数组适用于离线的区间修改问题 39 //常用结论:a[]的差分数组是diff[] 而diff[]的部分和数组是a[] 40 /*证明:sumd[i]=diff[1]+diff[2]+...+diff[i] 41 sumd[i]=a[1]+a[2]-a[1]+a[3]-a[2]+...+a[i]-a[i-1]=a[i]*/ 42 }
三.竞赛树
1 //竞赛树 2 /* 3 针对添加元素的数量确定的情况 4 使用多一倍的空间,换取代码实现上的方便 5 关键操作:上滤 6 一种很奇怪的数据结构..也不算奇怪总之做题时会有用处的。 7 数据都储存在叶子节点,内部节点储存子节点的较大值。 8 */ 9 #include<iostream> 10 using namespace std; 11 const int INF = 0x7fffffff/2; 12 const int MAXN = 5001; 13 struct tree{ 14 int data[MAXN*2]; 15 int n; 16 tree(int n) 17 { 18 this->n=n; 19 for(int i=1;i<=2*n-1;i++) data[i]=-INF; 20 } 21 void update(int pos, int value) 22 { 23 pos=pos+n-1; 24 data[pos]=value; 25 while(pos/=2) data[pos]=max(data[pos*2],data[pos*2+1]); 26 } 27 int top() { return data[1];}//返回最大值 28 int toppos()//返回最大值的位置 29 { 30 int pos=1; 31 while(pos<n) 32 { 33 if(data[pos]==data[pos*2]) pos=pos*2; 34 else pos=pos*2+1; 35 } 36 return pos-n+1; 37 } 38 }; 39 int main() 40 { 41 //..... 42 }
四.快速幂
1 //数论——快速幂 2 /* 3 计算 k^p%m 4 递归的版本(并不如位运算效率高),运算时采用乘法。 5 其实可以改成加法,使用加法更不容易爆longlong. 6 */ 7 #include<iostream> 8 #include<cstdio> 9 using namespace std; 10 int pow1(int k,int p,int m) 11 { 12 if(p == 0) return 1; 13 long long ans = pow1(k,p/2,m); 14 return p%2==1?(ans*ans*k)%m:(ans*ans)%m; 15 } 16 long long pow2(long long k,long long p,long long m) 17 { 18 if(p==0) return 1; 19 long long ans=pow2(k,p/2,m); 20 return p%2==1?(ans+k)%m:(ans+ans)%m; 21 } 22 int main() 23 { 24 long long k,p,m; 25 cin>>k>>p>>m; 26 cout<<k<<"^"<<p<<" mod "<<m<<"="<<pow2(k,p,m); 27 cout<<k<<"^"<<p<<" mod "<<m<<"="<<pow1(k,p,m); 28 return 0; 29 }
隐约雷鸣,阴霾天空,但盼风雨来,能留你在此。
隐约雷鸣,阴霾天空,即使天无雨,我亦留此地。