网站建设怎样中英文,网站建设php文件放哪里,腾讯云是做网站的吗,怎么把网页放到网站上本blog只是记录C学习以来掉过的一些坑#xff0c;写下来防止自己下一次再犯#xff0c;顺便分享 持续更新#xff0c;到死为止菜品特套1#xff1a;vector.size() ~ 的使用菜品特套2#xff1a;if-else的缩进菜品特套3#xff1a;int范围边界的1ll使用菜品特套4#xff…本blog只是记录C学习以来掉过的一些坑写下来防止自己下一次再犯顺便分享 持续更新到死为止菜品特套1vector.size() ~ 的使用菜品特套2if-else的缩进菜品特套3int范围边界的1ll使用菜品特套4内存计算菜品特套5全局变量和局部变量的重复菜品特套6顺序结构 ||前后顺序菜品特套7scanf(%s)与换行符的爱恨情仇菜品特套8break菜品特套9的差距菜品特套10STL的map/set菜品特套11C的执行顺序菜品特套12顺次处理字符读入菜品特套13传地址的动态开点菜品特套14异或判断相等的偷懒菜品特套1vector.size() ‘~’ 的使用
✔✔✔
for( int i G[u].size() - 2;i 0;i -- )❌❌❌
for( int i G[u].size() - 2;~ i;i -- )食用说明书食用说明书食用说明书 ~是用来判断是否为-1的简便写法 常见用法
跟前向星套用
memset( head, -1, sizeof( head) );
...
for( int i head[u];~ i;i nxt[i] )还有无限输入的判断 此时与EOF产生的作用一样 while( ~ scanf( %d, n ) )
//也可写作
while( scanf( %d, n ) ! EOF )以上操作一但出现符合−1-1−1就会结束程序跳出循环…… 但是倒回去仔细看错误的写法看似正确实则暗流涌动一句话就可以直击要害 G[u].size()0G[u].size()0G[u].size()0的时候怎么办 减完后变成−2-2−2 此时是判断不出来的就会一直死循环−2-2−2下去 PS此问题来自哲学的微笑——老刘疯狂嘲笑哈哈哈哈 菜品特套2if-else的缩进
✔✔✔
if( ... ) {for( int i 1;i n;i )if( ... )
}
else {...
}❌❌❌
if( ... )for( int i 1;i n;i )if( ... )
else...食用说明书食用说明书食用说明书 如果if−elseif-elseif−else和forforfor是这么操作那么运行就会很正常 满足ififif条件就执行iii的循环 否则执行jjj的循环
if( ... )for( int i 1;i n;i )...
elsefor( int j 1;j n;j )... 但是当我们在循环里面再次嵌套条件语句的时候此时就问题大大滴了 if−else用法if-else用法if−else用法 我们要了解if−elseif-elseif−else的运行原则elseelseelse在不加{}\{\}{}强制区分的时候是默认否定离它最近的ififif情况 也就是说在错误写法中elseelseelse否定的是forforfor循环里面的ififif条件 if−elseif-elseif−else是算一条语句的嵌套在循环里面时就可以不用打括号 for( int i 1;i n;i )if( ... ) ...else ...
//上面写法等价于下面的写法
//如果ifelse里面有多条语句的时候
//注意要打括号不然if-else会被中断出现CE
for( int i 1;i n;i ) {if( ... ) ...else ...
} if−elseif-elseif−else是一条语句所以中间是不能被其它非if−elseif-elseif−else语句打断 for( int i 1;i n;i )if( ... ) ...n n 1;else ...
//这个时候会if-else编译报错并且提醒我们缺少大括号往往题目的情况不止简简单单的两种这个时候我们一样处理
for( int i 1;i n;i ) if( ... ) ...else if( ... ) ...else if( ... ) ...else ...
//两种写法是等价的
for( int i 1;i n;i )if( ... )else if( ... ) ...else if( ... ) ...else ... 综上总结一下 我们的缩进只是为了代码可观逻辑清晰易懂 但是程序运行有自己严格的规则并不是智能AI 程序并不会按照我们的缩进智能分类匹配if−elseif-elseif−else PS此问题出自蒟蒻博主例题“zamjena”当时调了好几天自己也发现了加括号和不加括号会有答案的区别但是当时没有意识到本质的原因是什么
博主自我反思 有的时候觉得if-else很简洁而且我自己不太喜欢打大括号从而可以缩减代码行数 现在细想来觉得还是应该从严谨逻辑的角度出发还是打个大括号避免这种分歧 菜品特套3int范围边界的1ll使用
✔✔✔
long long n 1ll 31 - 1;
//运行结果2147483647❌❌❌
long long n 1 31 - 1;食用说明书食用说明书食用说明书 有符号整型int232int2^{32}int232占用4字节32bit 然而取值范围[−231,231−1][-2^{31},2^{31}-1][−231,231−1] 无符号整数unsigned_intunsigned\_intunsigned_int取值范围就可以达到[0,232−1][0,2^{32}-1][0,232−1] C计算的时候是默认intintint类型也就是说如果我们不强调1ll1ll1ll111就只申请了intintint类型 我们可能会以为我左边储存答案的变量开了longlonglong\ longlong long啊这不存的下嘛 其实不然可以理解为是右边每个计算部分存好后再统一进行操作 然后放到左边变量里面并不是直接在左边变量里面操作
延伸拓展
请看接下来的两种操作写法
int A, B;
long long n A B;long long A;
int B;
long long n A B;将A,BA,BA,B赋值214748364721474836472147483647 会发现第一种写法溢出了而第二种写法算出了正确答案 这是因为ABABAB暂时将结果存在了AAA里面然后再像赋值一样赋给nnn 可以试试A:int,B:longlongA:int,B:long\ longA:int,B:long long也是一样的 而第一种写法AAA是intintint类型的显然存不下所以就爆出去了 解决方法有两种 第一个就是像第二种写法一样直接把变量开成longlonglong\ longlong long 第二种就是计算时乘以1ll1ll1ll一般习惯在第一个变量前面加这样右边整个答案只要在longlonglong\ longlong long范围内都可以存储
int A, B;
long long n 1ll * A B;泼水不收
long long n ( 1 30 ) ( 1 30 ) - 1;
long long n ( 1 30 ) 3 - ( 1 30 ) - 4;
...
long long n ( 1 30 ) x - ( 1 30 ) - ( x 1 );
//可以试试这种写法
//x不要带得太大
//发现这种写法一样可以这是为什么呢留给dalao们蒟蒻不懂 蒟蒻bb 初学C学了很多算法 但是对这种知识真的是了解很少不懂计算机的运算法则 所以经常会在各种歪歪扭扭的角(ka)角(ka)落(guo)落(guo)到处爆掉 PS Upd–2020-06-11 老刘好SB哈哈哈哈写FWT板题(f[k]f[kp]mod)(f[k]f[kp]mod)%mod(f[k]f[kp]mod) 还不知道为什么错了要是f[k]f[kp]mod−1f[k]f[kp]mod-1f[k]f[kp]mod−1 三个加一起就爆intintint了呀我看了一眼就发现了哈哈哈哈哈 菜品特套4内存计算 做FMTFMTFMT州区划分给爷调崩了一直RERERE我都以为是被针对了 ✔✔✔
long long dp[23][1 22], g[23][1 22], inv[1 22];❌❌❌
long long dp[23][1 21], g[23][1 21], inv[1 21];食用说明书食用说明书食用说明书 1GB1024MB1024∗1024KB1024∗1024∗1024B(byte字节)1GB1024MB1024*1024KB1024*1024*1024B(byte 字节)1GB1024MB1024∗1024KB1024∗1024∗1024B(byte字节) 在 C 中 intintint类型每个空间是444个字节 longlonglong\ longlong long是888个字节 boolboolbool类型是111个字节 数组占用内存的计算 ①a[x][y]a[x][y]a[x][y]的空间大小x∗yx*yx∗y数组大小∗4*4∗4转化为ByteByteByte/1024/1024/1024转化为KBKBKB/1024/1024/1024转化为MBMBMB ②直接用sizeof(a)sizeof(a)sizeof(a)这样算出来的空间占存的单位是byte 看到这里的时候就已经明白自己是如何死得死翘翘的了 就以RERERE的数组大小来举栗计算 23∗(122)96468992∗4(B)/1024376832(KB)/1024368MB23*(122)96468992*4(B)/1024376832(KB)/1024368MB23∗(122)96468992∗4(B)/1024376832(KB)/1024368MB 按照intintint的字节数来计算就已经如此之大更何况开的是longlonglong\ longlong long内存算出来就要×2×2×2 涉及内存的一般都是卡你数据结构啊或者状压dpdpdp… 我认为学习C还是有必要掌握这么基本的内存计算方法因为编译器的不同对数组的最大忍受也不同可能编译能过但是交上去跑出来是RE这个时候调起来就会很崩溃... 菜品特套5全局变量和局部变量的重复
✔✔✔
#include cstdio
int n;void calc() {for( int i 1;i n;i )...
}int main() {n ...return 0;
}❌❌❌
#include cstdio
int n;void calc() {for( int i 1;i n;i )...
}int main() {int n ...return 0;
}食用说明书食用说明书食用说明书 太智障了这个坑一点都不想说fa 做的FMT遗失的答案掉的坑凸(艹皿艹 ) 局部变量只在局部内有值 全局变量适用于全局 局部内可以正确调用局部变量 局部外的其他版块一旦涉及到该变量默认调用全局 一言以蔽之局部内优先调用局部内的变量次调用全局变量 所以错误写法中calccalccalc版块的nnn其实是等于0的该forforfor循环根本未被执行 报告完毕 菜品特套6顺序结构 ||前后顺序
✔✔✔
bool vis[n 5];
while( x n vis[x] ) x y;❌❌❌
bool vis[n 5];
while( vis[x] x n ) x y;食用说明书食用说明书食用说明书 顺序结构大师上线 在我初学C的时候就曾经犯过这个问题没想到时隔多年再次煞笔 由∣∣\\\ || ∣∣连接的顺序结构 一连串的条件限制程序默认从左往右顺次判定 所以在错误写法中极有可能vis[x]vis[x]vis[x]就已经炸出visvisvis的范围了看都没看后面的条件限制 最终导致程序死亡 菜品特套7scanf(“%s”)与换行符的爱恨情仇
爷爷/奶奶你追的博客关注的大大更新了 因为真的被玄学到了所以单独开了一篇blog来写 这里直接上链接吧 五星菜品⑦ 菜品特套8break
原料来自于此blog题解的第二题 这里不谈正解只考虑用mapmapmap暴力搞的写法 因为我考场就是纯map ✔✔✔
for( int i 1, x;i m;i ) {scanf( %d, x );long long ans 0;bool no 0;for( int j 1;j x;j ) {cin s;if( mp[s] ) ans mp[s];else no 1;}if( no ) printf( -1\n );else printf( %lld\n, ans );
}❌❌❌
for( int i 1, x;i m;i ) {scanf( %d, x );long long ans 0;bool no 0;for( int j 1;j x;j ) {cin s;if( mp[s] ) ans mp[s];else { no 1; break; }}if( no ) printf( -1\n );else printf( %lld\n, ans );
}食用说明书食用说明书食用说明书 想必dalao看一眼就知道咋回事了 没错 breakbreakbreak结束当前循环 continue:continue:continue:结束当前情况并不结束当前循环 举个栗子
for( int i 1;i n;i )if( i 1 ) break;
for( int i 1;i n;i )if( i 1 ) continue;breakbreakbreaki1i1i1就直接结束循环了所以时间复杂度只有111 continuecontinuecontinueiii还是会把nnn以内的数都遍历一遍时间复杂度仍为O(n)O(n)O(n)
再多说几句break,continue...break,continue...break,continue...这种语句跟其他语句混用必须打大括号不认逗号
如果每一条语句之间都是逗号 计算机会一直读默认到最后分号出现的位置为一整条语句 所以就不用打大括号
但套上这种专有语句后就不行了 我也不造为什么
举个栗子 ✔
for( int i 1;i n;i )if( i 1 ) ans , p[ cnt] i;✔
for( int i 1;i n;i )if( i 1 ) { ans , p[ cnt] i; continue; }❌
for( int i 1;i n;i )if( i 1 ) ans , p[ cnt] i, continue;转回正题
因为我边读入边线性求解发现是穷人后就直接breakbreakbreak导致当前组数据压根没读完 再加之这道题是多组数据被我中间插断的数据就被我的计算机读入成为下一组数据了 菜品特套9的差距
我以为许久不更新以后就不会写sb锅了
✔✔✔
#include cstdio
void solve( int x ) {printf( %d\n, x );
}
int main() {int cnt 1;int pre cnt; solve( cnt );printf( %d, pre );return 0;
}
/*
输出
2
2
*/❌❌❌
#include cstdio
void solve( int x ) {printf( %d\n, x );
}
int main() {int cnt 1;int pre cnt, solve( cnt );printf( %d, pre );return 0;
}/*
输出
2
*/食用说明书食用说明书食用说明书 可能似个人就看出来了错误写法中intintint变量名的定义和函数调用中间用的逗号连接 之前也不是没犯过因为逗号死掉的问题这次又中了 逗号连接的在计算机里的默认是一句话 所以计算机将我的函数调用理解为了int solve(cnt)然后。。。。p都没干
菜品特套10STL的map/set
setsetset自动去重——解决方法重载排序 mapmapmap本质也是一个排序的不然为什么会有unorderd_map 所以如果传入的下标是多个元素必须重载排序才能编译成功 并且每一个元素都要参与排序 比如(1,2,3)(1,2,3)(1,2,3)(1,2,4)(1,2,4)(1,2,4) 只比较前两位参与排序那么setsetset自动去重了只留下一个mapmapmap则判断两者为一样的 灰常感谢香香mm的倾情赞助真是让吾辈受益匪浅呢%%%% 菜品特套11C的执行顺序
前言是在最近做的线段树优化建图时碰到的
addedge( u, cnt );
addedge( cnt, cnt );
addedge( v, cnt );这三条语句写者的想法是uuu向cntcntcnt点连边然后cntcntcnt向cntcntcntcntcntcnt先自加111连边vvv向cnt1cnt1cnt1连边
e.g. cnt1cnt1cnt1uuu向111连边111向222连边vvv向222连边
你就可以发现Dev-c被卡RE了
因为
c一条语句其实是从右往左读的
也就是说在第二条加边语句中是先cntcntcnt再cntcntcnt与cntcntcnt连边
这就连出了自环的无限循环了
所以必须这么写
addedge( u, cnt );
addedge( cnt, cnt 1 );
addedge( v, cnt );这也能说明有的时候我们会像下面这么连续赋值
int a, b, c, d;
a b c d 419;先执行d419然后cd接着bc最后ab成功赋值四个变量
菜品特套12顺次处理字符读入
最近都有碰到字符串读入的处理
众所周知只有空格和换行是非常头疼的
而且现在随着版本的更新gets()已经不允许使用了但是它的功能真的很舒服啊可以读入空格和换行哎可以试试fgets()但建议还是别了吧
一般读入字符串的方法如下
一个一个字符地读chgetchar()scanf(%c,ch) 好处自然是可以通过条件语句判断空格和换行做出相应举措一个字符串一个字符串地读scanf(%s,s)cins 但都是遇到空格或者换行就直接结束了便于我们直接处理不要空格和换行的题目
但是博主最近的问题是需要空格和换行那么就选择了一个一个字符地读
结果总是忘记最后一个字符串是留下来未操作的因为后面是空不能触发处理一个字符串的结束条件
经常最后一个字符串被遗忘导致出错丢分 菜品特套13传地址的动态开点
最近做了两道题是需要可持久化字典树的。
而可持久化标准需要动态开点所以大家都习惯于直接把数组的地址传过去这样就直接改了数组。
但是字典树的可持久化就不要传了。
void insert( int lst, int now, char s ) {now cnt; t[now] t[lst];for( int i 1;i n;i ) {int c s[i] - a;t[now].son[c] cnt;now t[now].son[c];lst t[lst].son[c];t[now] t[lst];}
}
insert( root[i - 1], root[i], s[i] );受到可持久化字典树的影响实在太大了。
上面的写法完全是错误的因为 nownownow 从始至终都带的是地址所以看似我们走了 nownownow 的儿子边但是其实一直都是 root[i]root[i]root[i] 的编号在自加。
只有 lstlstlst 版本的字典树一直在正确的走。
所以字典树的就不要传地址了直接改原数组得了。
void insert( int lst, int now, char s ) {root[now] cnt; now root[now];lst root[lst];t[now] t[lst];for( int i 1;i n;i ) {int c s[i] - a;t[now].son[c] cnt;now t[now].son[c];lst t[lst].son[c];t[now] t[lst];}
}
insert( i - 1, i, s[i] );菜品特套14异或判断相等的偷懒
因为本人的码风和个人喜好问题比起来 ! 我更喜欢 ^ 而且少占一个字符。
众所周知 x^x0所以我很喜欢if(a^b) ... 这种写法。
这倒是没什么问题因为 if-else 这种判断句又是 bool\text{bool}bool 类的只认 0/10/10/1。
但是写多了就以为本身运算就是个 0/10/10/1 的返回。
比如我的本意是如果 x≠yx\ne yxy 就 111否则 000。
写代码就容易写成 ans(x^y)。
这简直就是大错特错现在的 x^y 明显是个运算了而不是 [x^y] 的条件判断。
不如老老实实写 ! 因为这个真的很难调思维进入一个误区跳出来很困难的欸。