集训Day 6
Double 心态=0,自信=0,勇猛=0;
比赛开始,由于起晚了10分钟(心态-=50%;)心态不好,看了一眼第一题,很简单,一定能写对!但写了估摸10min还是没过样例(自信-=90%;)就换了一种写法调了30min才过了所有样例,(自信-=100%;),接着看第二题,题目数据比较水就慌忙写了一个DFS水一发,没想到竟然过了大样例(自信+=50%,心态+=40%,勇猛+=100%;)确认不会越界后就继续看第三题啊?题目讲的是什么?怎么办?模拟?(勇猛-=50%,心态-=10%;)我赶紧整了几个数模拟了一下想到了一个需要用收值域影响的暴力,但害怕像上次一样数组开太大过不了编译就想其他的方法去了,后来一直没想到什么好的方法(勇猛=0%,心态=BOOM!,自信=10%;),时间也过了40来分钟就想了一个由类似堆顶堆优化的受值域影响的暴力,但过了大样例!(心态=50%,自信=50%,勇猛=100%)好,康康第四题,这道题明显DP但是我写不出来(心态=-∞,自信=-∞,勇猛=-∞)成功触发被动技能:暴力!写了一个暴力保分以后就没了。
TIPS: 1. string 提取子串时,一般第一个参数是左端点,第二个参数是长度(例如:S.substr(l, len), S1 = string(S, l, len)) 2. 一定要注意搜索顺序问题,对于 DFS 而言是搜到之前已经处理好信息还是搜到之后先处理好信息再接着搜,对于 BFS 而言是取出之后处理好还是放入之前处理好 3. STL 容器不能边使用迭代器遍历边改动内部结构,如插入等 4. 注意 long long, 多测清空,测大样例要看仔细 5. strcmp 会根据编译器和编译选项返回 -1 或者 -3,-4 等,所以一定要使用 strcmp>0 或者 strcmp<0,不要写 strcmp == 1 6. 大样例不一定靠谱,争取学会自己造数据和对拍 7. 碰到可以进行任意多次减法操作的题目一般考虑最大公约数(因为 x<y 时,让 y 任意减去 x 相当于 y % x,变为辗转相除法) 8. 动态规划扩展:从暴力搜索出发,思考什么是「状态」,为什么那么多 2^n 级别的状态可以用 n 个最优状态取代 9. DP 最忌惮似是而非,当你觉得自己听了也看了标程和题解甚至是自己之前AC过的题目你非常有可能不会,这是很危险的。
第三题题解:
如果可以对所有数字任意执行减法,根据辗转相减
法原理,那么最后能得到的最小的数字便是所有数字的 gcd。
所以求出所有数字的 gcd,答案便是最大的数字除以这个 gcd。
第一题程序:
#include<bits/stdc++.h> using namespace std; string S,T; int main() { ios::sync_with_stdio(false); cin>>S>>T; int q,l1,l2,r1,r2; cin>>q; while(q--) { cin>>l1>>r1>>l2>>r2; string s,t; for(int i=l1-1;i<r1;i++) s+=S[i]; for(int i=l2-1;i<r2;i++) t+=T[i]; if(s>t) printf("Second\n"); else if(s<t) printf("First\n"); else printf("OVO\n"); } return 0; }
第二题程序:
#include<bits/stdc++.h> using namespace std; const int N=1e6+10; int n,m,cnt=0; vector<int > mp[N]; void dfs(int k,int step) { if(k==n&&step==2) cnt=1; if(cnt==1||step>=2) return; for(int i=0;i<mp[k].size();i++) dfs(mp[k][i],step+1); } int main() { ios::sync_with_stdio(false); int t; cin>>t; while(t--) { cnt=0; cin>>n>>m; for(int i=1;i<=n;i++) mp[i].clear(); for(int i=1;i<=m;i++) { int u,v; cin>>u>>v; mp[u].push_back(v); } dfs(1,0); if(cnt==1) printf("POSSIBLE\n"); else printf("IMPOSSIBLE\n"); } return 0; }
第三题程序:
#include<bits/stdc++.h> using namespace std; const int N=1e5+5; int n,a[N],maxn=-100,t,minn=0x3f3f3f3f,maxi; int gcd(int a,int b) { if(b==0) return a; else return gcd(b,a%b); } int main() { ios::sync_with_stdio(false); cin>>t; while(t--) { maxi=0; cin>>n; for(int i=1;i<=n;i++) cin>>a[i],maxi=max(a[i],maxi); minn=a[1]; for(int i=2;i<=n;i++) { minn=min(minn,gcd(minn,a[i])); if(minn==1) break; } printf("%d\n",maxi/minn); } return 0; }
第四题程序:
#include<bits/stdc++.h> using namespace std; const int N=5005; int n,m,x[N]; long long bonus[N],f[N][N]; int main() { ios::sync_with_stdio(false); cin>>n>>m; for(int i=1;i<=n;i++) cin>>x[i]; for(int i=1;i<=m;i++) { int c,y; cin>>c>>y; bonus[c]+=y; } memset(f,-0x3F,sizeof(f)); f[0][0]=0; for(int i=1;i<=n;i++) { for(int j=0;j<=n;j++) f[i][0]=max(f[i][0],f[i-1][j]); for(int j=1;j<=n;j++) f[i][j]=f[i-1][j-1]+x[i]+bonus[j]; } long long ans=0; for(int j=0;j<=n;j++) ans=max(ans,f[n][j]); cout<<ans; return 0; }