50% 占比,小技巧:
// 行数是列数的50%(四舍五入取整) int n; cin>>n; int col=n,row=n-n/2;
模仿 split 分割小技巧:
string s="abc 123 . ",ts; stringstream ss(s); int k=0; while(ss>>ts) { k++; cout<<ts<<endl; cout<<k<<endl; }
map<string, int> 搭配 scanf:
map<string,int> mp; char s1[100]; scanf("%s",s1); mp[s1]=1; // 容易 TLE string s2; cin>>s2; mp[s2]=1;
翻译:
1、“a by b” // a * b
对于局部数组来讲:如果数组在定义声明顺便初始化的时候,只要前面有数据赋值,多少个都可以,至少有一个即可,则,其后的数组里的元素全部为0,所以一般 int a[100]={0}; 并不是把全部数组元素变为0,而是因为刚刚说的这个原理。如果改成 int a[100]={1,2,3}; 则前3个为1,2,3,但后面都为0。
首尾空格处理 + strncpy:
/
// 首尾空格处理 int l=0,r=k-1; while(s[l]==' ') l++; while(s[r]==' ') r--; strncpy(s,s+l,r-l+1); ts[r-l+1]=0;
strtok 函数:
char str[] = "I am a stduent,you are teacher!"; const char spliter[] = " ,!"; char * pch; pch = strtok( str, spliter ); while( pch != NULL ) { cout << pch << endl; pch = strtok( NULL, spliter ); }
lower_bound / upper_bound 函数:
/* 数组从 1 开始存储,但是查找的时候依然是从 0 开始,因为若当待查找的数据>最大值,return 数组大小;若<最小值,return 0;而如果不从 1 开始存储的话,当 return 0 时,不知道是查找到第一个数据还是因为没找到的缘故。 */ int l=lower_bound(a,a+n+1,b)-a; // 在 a[i] 中,返回第一个大于等于 b 的数字的对应位置 int r=upper_bound(a,a+n+1,b)-a; // 在 a[i] 中,返回第一个大于 b 的数字的对应位置 int rs=r-l; // 表示有 rs 个等于 b 的数
四舍五入到整数小技巧:
printf("%d",(int)(x+0.5)); // 比下面这种写法有时更加精确 printf("%.0f",double(x));
- 上下界针对 y轴 来说,所以上界显然大于等于下界,也就是说:区间[下界,上界]。
- 进制互转:
/* 10进制转任意进制 */ void D2Any(int x,int r) { int a,b=x,k=0,ans[100]; while(1) { a=b%r; b=b/r; ans[k++]=a; if(x/r==0) break; x/=r; } for(k--;k>=0;k--) { if(ans[k]>9) printf("%c",ans[k]+87); // 87:小写,55:大写 else printf("%d",ans[k]); } } /* 任意进制转10进制 */ ll Any2D(char x[],int r) { int len=strlen(x),tmp=1; ll ans=0; for(int i=len-1;i>=0;i--) { if(x[i]>='0' && x[i]<='9') ans+=(x[i]-'0')*tmp; else ans+=(x[i]-'a'+10)*tmp; tmp*=r; } return ans; }
0.000005 处理精度丢失问题,具体要加多少个“0”,看题目的保留多少位的情况再做分析。
变量的 初始化 和 定义,尽量跟业务逻辑的代码紧挨在一起;先业务逻辑,需要用到的变量再往上面补充。
日期比较 y*10000 + m*100 + d 小技巧。
差分前缀和小技巧:点击打开链接
输入一个十进制,统计它的二进制数中“1”的个数
/
int cnt1(int x) { int cnt=0; while(x) cnt++, x=x&(x-1); return cnt; }
输出格式控制:
// 第一种 4 line 每次都要判断相对来说也消耗 for(int i=0;i<n;i++) if(i) printf(" %d",a[i]); else printf("%d",a[i]); puts(""); // 第二种 4 line printf("%d",a[0]); for(int i=1;i<n;i++) printf(" %d",a[i]); puts(""); // 第三种 3 line // 最好不要从0开始,否则每次都要 -1 相对来说也要消耗(即使可忽略不计),所以从1开始比较好 for(int i=1;i<n;i++) printf("%d ",a[i]); printf("%d\n",a[n]); // 第四种 2 line for(int i=0;i<n;i++) printf("%d%c",i==n-1?'\n':' ');
输入格式控制:
char ch; scanf(" %c", &ch); // 百分号之前有一个空格,这样scanf会首先过滤掉所有的空格、制表符和换行符 /* 常见吸收回车写法 */ char ch; int n; scanf("%d",&n); getchar(); // 不推荐 scanf("%c",&ch); scanf("%d",&n); scanf(" %c",&ch); // 推荐
输入(一行有空格的字符串),希望不包括空格以 '\n' 结束:
/* 用 do-while 免得最后一次数据('\n'前)还要额外处理 */ do { scanf("%s",key); nds[i].kv.push_back(key); }while(getchar()!='\n');
利用格式符 “%[]” 作用:为扫描字符集合:
scanf("%[^c]", str);
其中 “c” 是一个具体的字符常量(包括控制字符)。
C语言中 scanf() 函数提供的 “%[]” 格式串可以用来进行多个字符的输入,并对结束符进行自定义。对于 %[] 还可以用 ^+ 任意字符(包括 eof)来结束字符串的输入,如 %[^EOF] 就是直到有 EOF 输入,字符串才中止。
/
scanf("%[^\n]", str); // 以换行符作为字符串输入的结束(可包含空格)
针对非升序 / 非降序操作,如果相等按照原来输入的顺序进行排序(通过伪优先级控制):
struct node { int ge,pri; }nds[100005]; int cmp(node n1,node n2) // 非升序 { if(n1.ge==n2.ge) return n1.pri<n2.pri; return n1.ge>n2.ge; }
自定义进制(模仿 hh: mm: ss)
typedef long long ll; int main() { ll a1,b1,c1,a2,b2,c2; scanf("%lld.%lld.%lld%lld.%lld.%lld",&a1,&b1,&c1,&a2,&b2,&c2); ll rs=c1+b1*29+a1*17*29+c2+b2*29+a2*17*29; // rs(秒) hh=rs/3600 mm=rs%3600/60 ss=rs%60 printf("%lld.%lld.%lld\n",rs/(17*29),rs%(17*29)/29,rs%29); return 0; }
大数比较小技巧点击打开链接
double 判 0 小技巧:
double A; scanf("%lf",&A); if(A+0.005>=0&&A<0) printf("0.00"); // 1 if(fabs(A)<0.0005) printf("0.00"); // 2 推荐
矩阵区分八个方向是【越界】or【题目条件】的区分小技巧:
int pas=1, k=0; // 这里 pas 不能从 0 开始,否则会影响判断 if(i-1>=0 && pas++ && abs(a[i-1][j]-d)>st) k++; if(i-1>=0 && j+1<m && pas++ && abs(a[i-1][j+1]-d)>st) k++; if(i-1>=0 && j-1>=0 && pas++ && abs(a[i-1][j-1]-d)>st) k++; if(j-1>=0 && pas++ && abs(a[i][j-1]-d)>st) k++; if(j+1<m && pas++ && abs(a[i][j+1]-d)>st) k++; if(i+1<n && pas++ && abs(a[i+1][j]-d)>st) k++; if(i+1<n && j-1>=0 && pas++ && abs(a[i+1][j-1]-d)>st) k++; if(i+1<n && j+1<m && pas++ && abs(a[i+1][j+1]-d)>st) k++; if(k+1==pas) return 1;
有时候创建数据结构的情况比较复杂的时候,先不要急于创建,可以在思路Coding的过程中,发现需要用到哪个变量就创建哪个变量。
判断语句原则:先判断再决定;而不是先决定再判断。
数组初始化的三种常用方法:for循环浪费的时间最多,{0} 与 memset 耗时差不多。
PAT的题目因为时间控制严格,而且它评测机制每次都一个测试用例一次,所以不到万不得已,不要像平常ACM一样去做清空操作。
heap:
// 边插入边建堆 for(int i=1;i<=n;i++) { scanf("%d",&a[i]); make_heap(a+1,a+1+i,greater<int>()); // min heap } // 先建树再调整堆 make_heap(a,a+n); // max heap
区间合并小技巧:点击打开链接
在DFS中途就可以输出结果并且结束整个程序技巧
exit(0);
- '\0' 输出不是什么都没有,而是一个类似的空格,当它用 %c 单独输出时。
- 待更新...