2021.07.18暑假集训(前缀和+枚举)
1.二维数组的前缀和的表示方法,就是(0,0)点到右下角点的总和
sum[i][j] = mp[i][j] + sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1]; //某一点的前缀和 = 该点值 + 上面一点的前缀和 + 左边一点的前缀和 - 上边和左边重叠的部分
或者用:
for(int i=0;i<=5000;i++){ int s=0; for(int j=0;j<=5001;j++){ s+=a[i][j]; x[i][j]=s; } }//每一行的总和 for(int i=0;i<=5001;i++){ for(int j=0;j<=5001;j++){ if(i==0){ a[i][j]=x[0][j]; }else{ a[i][j]=a[i-1][j]+x[i][j]; } } }//这一行的总和加上一行的前缀和
说明:
1.一定注意越界的问题,一般限制长度为k的时候最好是从k~n,不要从0-n-k+1
2.奇♂妙拆分 (nowcoder.com)直接暴力枚举即可,不用想太多的什么质因子分解之类的
3.「土」巨石滚滚 (nowcoder.com)解题的时候分了三种情况:
1)bi-ai>0——>这种情况就是增长体力,此时可以很容易的想到先收ai小的,反正都是增长体力
2)bi-ai=0——>这种情况只是比较是不是会出现现在的体力不能够大于ai
3)bi-ai<0——>这种情况,可以用公式推一下,AB可以但是BA不可以的时候,或者说AB体力比BA体力剩余多的情况下是什么,也就是出现了-Aa+Ab-Ba>-Ba+Bb-Aa,此时可以得到必须是bi大的在前面才可以
4.next_permutation的用法
int main(){ int a[8]={1,2,3,4,5,6,7,8}; sort(a,a+8); do{ //cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<" "<<a[3]<<endl; for(int i=0;i<8;i++) cout<<a[i]<<" "; cout<<endl; }while(next_permutation(a,a+8)); }