A:直接1,2,1,2的送,答案就是n / 3 * 2 + (n % 3 != 0)
#include <iostream> #include <cstring> #include <cstdio> using namespace std; int n; int main() { cin>>n; cout<<n / 3 * 2 + (n % 3 != 0); }
B:按照原图中的箭头跳,跳出了就是false,如果跳到了以前访问的点就是true.
#include <iostream> #include <cstring> #include <cstdio> using namespace std; int n,A[100010]; bool visit[100010]; char s[100010]; int main() { //freopen("lx.in","r",stdin); cin>>n; scanf("%s",s + 1); for(int i = 1;i <= n;i ++) scanf("%d",&A[i]); int x = 1; memset(visit,false,sizeof(visit)); while(1) { if(visit[x]) {printf("INFINITE");return 0;} visit[x] = true; if(s[x] == '>') { x = x + A[x]; if(x <= 0 || x > n) {printf("FINITE");return 0;} } else { x = x - A[x]; if(x <= 0 || x > n) {printf("FINITE");return 0;} } } }
Div2 C & Div1 A :
按照题意暴力模拟,f[i][j]表示i行j列实际表示的是原来矩阵的哪一个数.
#include <iostream> #include <cstring> #include <cstdio> using namespace std; int n,m,q,a,b,c,father[110][110],Ans[110][110],op; int main() { //freopen("lx.in","r",stdin); scanf("%d%d%d",&n,&m,&q); for(int i = 1;i <= n;i ++) for(int j = 1;j <= m;j ++) father[i][j] = (i - 1) * m + j; for(int i = 1;i <= q;i ++) { scanf("%d",&op); if(op == 1) { scanf("%d",&a); int t = father[a][1]; for(int j = 1;j < m;j ++) father[a][j] = father[a][j + 1]; father[a][m] = t; } if(op == 2) { scanf("%d",&a); int t = father[1][a]; for(int j = 1;j < n;j ++) father[j][a] = father[j + 1][a]; father[n][a] = t; } if(op == 3) { scanf("%d%d%d",&a,&b,&c); int t = father[a][b]; int x = (t - 1) / m + 1; int y = t - (x - 1) * m; Ans[x][y] = c; } } for(int i = 1;i <= n;i ++) { for(int j = 1;j <= m;j ++) { cout<<Ans[i][j]<<' '; } cout<<endl; } }
Div2 D & Div1 B :
分析一下发现奇数的男生的移动是相似的,偶数之间也是相似的,所以只用分别算出奇数和偶数分别移动了多少就可以了.(注意中途爆int.T_T)
#include <iostream> #include <cstring> #include <cstdio> using namespace std; int n,q,A[2000010],B[2000010],Ans[1000010],step; int main() { scanf("%d%d",&n,&q); for(int i = 1;i <= q;i ++) { scanf("%d",&A[i]); if(A[i] == 1) scanf("%d",&B[i]); } step = 0; for(int i = 1;i <= q;i ++) { if(A[i] == 1) step = ((step + B[i]) % n + n) % n; else if((step + 1) % 2 == 0) step = ((step - 1) % n + n) % n; else step = ((step + 1) % n + n) % n; } for(int i = 1;i <= n;i += 2) Ans[(((i + step) % n) + n) % n] = i; step = 0; step = 0; for(int i = 1;i <= q;i ++) { if(A[i] == 1) step = ((step + B[i]) % n + n) % n; else if((step) % 2 == 0) step = ((step - 1) % n + n) % n; else step = ((step + 1) % n + n) % n; } for(int i = 2;i <= n;i += 2) Ans[(((i + step) % n) + n) % n] = i; Ans[n] = Ans[0]; for(int i = 1;i <= n;i ++) printf("%d ",Ans[i]); }
Div1 C :
设Max[i] = max(a,b) <= i,Min[i] = min(a,b) >= i,s[i] = pa[1] + pa[2] +...pa[i],t[i] = pb[1] + pb[2] +..退一下公式发现s[i] * t[i] = Max[i],1 - s[i] - t[i] + s[i] * t[i] = Min[i + 1],解一下每个方程就可以了,注意sqrt()里面的数要和0取max...
#include <iostream> #include <cstring> #include <cstdlib> #include <string> #include <cstdio> #include <algorithm> #include <cmath> #include <ctime> #define g(a) a<0?-a:a using namespace std; int n; double Max[100010],Min[100010],s[100010],t[100010]; int main() { scanf("%d",&n); for(int i = 1;i <= n;i ++) scanf("%lf",&Max[i]); for(int i = 1;i <= n;i ++) scanf("%lf",&Min[i]); for(int i = 1;i <= n;i ++) Max[i] += Max[i - 1]; for(int i = n;i >= 1;i --) Min[i] += Min[i + 1]; for(int i = 1;i <= n;i ++) { double val = 1.0 - Min[i + 1] + Max[i]; double delta = val * val - 4.0 * Max[i]; s[i] = (val + sqrt(g(delta))) / 2.0; t[i] = val - s[i]; } for(int i = 1;i <= n;i ++) printf("%0.10f ",s[i] - s[i - 1]); cout<<endl; for(int i = 1;i <= n;i ++) printf("%0.10f ",t[i] - t[i - 1]); return 0; }
Div2 E & Div1 D :
按照询问的数排序,那么对于一段连续的询问其实询问的都是一个数,那么区间线段树加加减减就可以了.
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; struct node {int v;int t;int op;int id;}; node A[1000010]; int tot,v[1000010],flag[8000010],val[8000010],n,Ans[1000010]; bool comp(const node &x,const node &y) { if(x.v != y.v) return x.v < y.v; return x.id < y.id; } int hash(int x) { int head = 1,tail = tot,ret; while(head <= tail) { int Mid = (head + tail) >> 1; if(v[Mid] <= x) ret = Mid,head = Mid + 1; else tail = Mid - 1; } return ret; } void Add(int Now,int l,int r,int x,int y,int z,int w) { if(l >= x && r <= y) { if(flag[Now] != z && flag[Now] != 0) { flag[Now] = z; val[Now] = w; } else flag[Now] = z,val[Now] += w; return ; } int Mid = (l + r) >> 1; if(x <= Mid) Add(Now << 1,l,Mid,x,y,z,w); if(y > Mid) Add(Now << 1 | 1,Mid + 1,r,x,y,z,w); } int Ask(int Now,int l,int r,int x,int y) { if(l == r) { if(flag[Now] == y) return val[Now]; return 0; } int Mid = (l + r) >> 1,ret = 0; if(flag[Now] == y) ret += val[Now]; if(x <= Mid) return ret + Ask(Now << 1,l,Mid,x,y); else return ret + Ask(Now << 1 | 1,Mid + 1,r,x,y); } int main() { scanf("%d",&n); for(int i = 1;i <= n;i ++) { scanf("%d%d%d",&A[i].op,&A[i].t,&A[i].v); v[ ++tot] = A[i].t;A[i].id = i; } sort(v + 1,v + tot + 1); for(int i = 1;i <= n;i ++) A[i].t = hash(A[i].t); sort(A + 1,A + n + 1,comp); for(int i = 1;i <= n;i ++) Ans[i] = -1; for(int i = 1;i <= n;i ++) { if(A[i].op == 1) Add(1,1,n,A[i].t,n,A[i].v,1); if(A[i].op == 2) Add(1,1,n,A[i].t,n,A[i].v,-1); if(A[i].op == 3) Ans[A[i].id] = Ask(1,1,n,A[i].t,A[i].v); } for(int i = 1;i <= n;i ++) if(Ans[i] != -1) printf("%d\n",Ans[i]); return 0; }
然而Div1 E,F出题人都没写题解...(我就这两道做不来结果他就没写题解啊啊啊啊...)