D题:用来对比的vector<long long> b不能被初始化大小成n,因为a里面有n个因子,但是这是可能存在遗漏情况的。如果刚好是遇到实际因子远多于n,那么就会在运行过程中出错。
还有一开始写的时候没有考虑到另一边的因子,只有一半肯定出错。
出错代码:
#include<bits/stdc++.h> using namespace std; #define sc scanf #define pt printf #define maxn 305 #define mll long long int main() { int t; sc("%d",&t); while(t--) { int n,i; sc("%d",&n); vector<mll> a(n); for(i=0;i<n;++i) sc("%lld",&a[i]); sort(a.begin(),a.end()); mll ans = a[0]*a[n-1]; vector<mll> b(n,-1); int cnt = 0; for(i=2;i*1LL*i<=ans;++i) { if(ans%i==0) { b[cnt++]=i; if(ans/i!=i) b[cnt++]=ans/i; } } sort(b.begin(),b.end()); if(a==b) pt("%lld\n",ans); else { pt("-1\n"); } } return 0; }
成功代码:
#include<bits/stdc++.h> using namespace std; #define sc scanf #define pt printf #define maxn 305 #define mll long long int main() { int t; sc("%d",&t); while(t--) { int n,i; sc("%d",&n); vector<mll> a(n); for(i=0;i<n;++i) sc("%lld",&a[i]); sort(a.begin(),a.end()); mll ans = a[0]*a[n-1]; vector<mll> b; for(i=2;i*1LL*i<=ans;++i) { if(ans%i==0) { b.push_back(i); if(ans/i!=i) b.push_back(ans/i); } } sort(b.begin(),b.end()); if(a==b) pt("%lld\n",ans); else { // for(i=0;i<a.size();++i) pt("%lld%c",a[i]," \n"[i==a.size()-1]); // for(i=0;i<b.size();++i) pt("%lld%c",b[i]," \n"[i==b.size()-1]); pt("-1\n"); } } return 0; }
E题:结果和直接得到结果的值都考虑到了要用long long,但是没想到中间的i被设定成int型,由于n最大是200000,为了计算方便,我把n加了1,用于表示被取得的总次数i*(n-i)超过了int的范围,导致出错。
完整错误句子是:a[i]*=( i*(n-i) ); 我真的,可能一开始下意识地觉得a[i]是long long就没关系了吧。
成功代码:
#include<bits/stdc++.h> using namespace std; #define sc scanf #define pt printf #define maxn 200005 #define mll long long #define mod 998244353 mll a[maxn],b[maxn]; int main() { mll n,i; sc("%lld",&n); ++n; for(i=1;i<n;++i) { sc("%lld",&a[i]); a[i]*=( i*(n-i) ); } sort(a+1,a+n); for(i=1;i<n;++i) sc("%lld",&b[i]); sort(b+1,b+n); mll ans = 0; for(i=1;i<n;++i){ ans = ( ans + a[i]%mod*b[n-i]%mod )%mod; } pt("%lld\n",ans); return 0; }
F题:补题过程发现的不足和错误
不足:
(1)代码查错能力,没出正确结果很懵逼,不知道应该从哪里开始查。总觉得是数组越界,结果发现是-1越界而不是靠近正无穷一端越界。
(2)在回顾代码的时候会把自己看懵掉,不知道这个数组具体用来干嘛。
所以要多查多写,命名规范,最重要的是,先整理好思路知道自己在吗干嘛,最好在第一遍的时候把思路写在模块前面,也方便查错。
错误:
(1)促销商品剩余量的位置和促销商品的种类号一开始没对齐,一个从0开始,一个从1开始。
(2)下标越界,有些商品在截至日期之前是没有促销时间的,被我标成了-1.那么我将商品和促销时间联系在一起的时候(把商品标号压入对应促销时间的数组),就会导致运行时错误。
(3)边界处理,在第1000天的时候还是有可能有促销活动的,写成if(i>=1000) continue就会漏掉这个过程。
思考:能不能不用这个边界判断条件呢?那就要记录ddl之前的最晚促销时间了。
代码F1:
#include <bits/stdc++.h> #define pt printf #define sc scanf #define maxn 1005 #define ull unsigned long long #define inf 0x3f3f3f3f using namespace std; int N,M; typedef struct ob{ int day; int type; }ob; ob x; vector<ob> off(maxn,{inf,inf}); int cmp(ob p,ob q) { return p.day < q.day ; } int can( int ddl ,vector<int> y) { //req每次都会复制need数组,来模拟每次购买后还有多少商品需要购买 vector<int> req(y) ; vector<int> inwhichdayihavesale(N,-1); vector<vector<int> > sale(maxn); int i,j,len; for(i=0;i<M;++i) { //当前时间在截至日期之前 if(off[i].day<=ddl) { //更新对应的商品的促销时间,取靠后的时间 inwhichdayihavesale[off[i].type] = max (inwhichdayihavesale[off[i].type],off[i].day) ; } else { //我们已经对它排过序了,之后的时间肯定大于截至日期 break; } } for(i=0;i<N;++i) { //pt("inwhichdayihavesale[i] = %d\n",inwhichdayihavesale[i]); //为什么会有上面这个注释呢?因为不是所有的商品在截至日期之前都有促销活动的 //没有促销活动的商品的促销时间我标记成了-1 if(inwhichdayihavesale[i]!=-1) sale[inwhichdayihavesale[i]].push_back(i); } int cur = 0; for(i=1;i<=ddl;++i) { ++cur; //之前写成了if(i>=1000) 可是第1000天的时候还是有可能有促销活动呀 if(i>1000) continue; len = sale[i].size(); for(j=0;j<len;++j){ //req[ sale[i][j] ] : 第i天的第j件促销商品的剩余量 if(cur>=req[ sale[i][j] ]) { cur-= req[ sale[i][j] ]; req[ sale[i][j] ] = 0; } else { req[ sale[i][j] ] -= cur; cur = 0; break; } } } int res = accumulate(req.begin(),req.end(),0) * 2; //剩下商品需要的钱比已经积攒的钱多,那么就不能在截至日期之前成功买完所有的商品 if(res>cur) return 0; return 1; } int main() { sc("%d%d",&N,&M); //need代表第i种商品需要购买need[i]个。 vector<int> need(N,0); int i; for(i=0;i<N;++i) sc("%d",&need[i]); for(i=0;i<M;++i) { sc("%d%d",&off[i].day,&off[i].type); //因为我的need是从0开始的,所以商品种类应该减1. --off[i].type; } //根据促销时间先后排序,先发生的在前面 sort(off.begin(),off.end(),cmp); int l = 0, r = 2000 , ans = 2000, mid; while(l<=r) { mid = (l+r)>>1 ; if( can(mid,need) ){ ans = mid ; r = mid - 1; }else{ l = mid + 1; } } pt("%d\n",ans); return 0; }
代码F2:
#include <bits/stdc++.h> #define pt printf #define sc scanf #define maxn 200005 #define ull unsigned long long #define inf 0x3f3f3f3f using namespace std; int N,M; typedef struct ob{ int day; int type; }ob; ob x; vector<ob> off(maxn,{inf,inf}); int cmp(ob p,ob q) { return p.day < q.day ; } int can( int ddl ,vector<int> y) { //req每次都会复制need数组,来模拟每次购买后还有多少商品需要购买 vector<int> req(y) ; vector<int> inwhichdayihavesale(N,-1); vector<vector<int> > sale(maxn); int i,j,len; for(i=0;i<M;++i) { //当前时间在截至日期之前 if(off[i].day<=ddl) { //更新对应的商品的促销时间,取靠后的时间 inwhichdayihavesale[off[i].type] = max (inwhichdayihavesale[off[i].type],off[i].day) ; } else { //我们已经对它排过序了,之后的时间肯定大于截至日期 break; } } for(i=0;i<N;++i) { //pt("inwhichdayihavesale[i] = %d\n",inwhichdayihavesale[i]); //为什么会有上面这个注释呢?因为不是所有的商品在截至日期之前都有促销活动的 //没有促销活动的商品的促销时间我标记成了-1 if(inwhichdayihavesale[i]!=-1) sale[inwhichdayihavesale[i]].push_back(i); } int cur = 0; for(i=1;i<=ddl;++i) { ++cur; //之前写成了if(i>=1000) 可是第1000天的时候还是有可能有促销活动呀 if(i>200000) continue; len = sale[i].size(); for(j=0;j<len;++j){ //req[ sale[i][j] ] : 第i天的第j件促销商品的剩余量 if(cur>=req[ sale[i][j] ]) { cur-= req[ sale[i][j] ]; req[ sale[i][j] ] = 0; } else { req[ sale[i][j] ] -= cur; cur = 0; break; } } } int res = accumulate(req.begin(),req.end(),0) * 2; //剩下商品需要的钱比已经积攒的钱多,那么就不能在截至日期之前成功买完所有的商品 if(res>cur) return 0; return 1; } int main() { sc("%d%d",&N,&M); //need代表第i种商品需要购买need[i]个。 vector<int> need(N,0); int i; for(i=0;i<N;++i) sc("%d",&need[i]); for(i=0;i<M;++i) { sc("%d%d",&off[i].day,&off[i].type); //因为我的need是从0开始的,所以商品种类应该减1. --off[i].type; } //根据促销时间先后排序,先发生的在前面 sort(off.begin(),off.end(),cmp); int l = 0, r = 400000 , ans = 400000, mid; while(l<=r) { mid = (l+r)>>1 ; if( can(mid,need) ){ ans = mid ; r = mid - 1; }else{ l = mid + 1; } } pt("%d\n",ans); return 0; }