A - 9x9
很简单,自己做
B - tcaF
直接计算阶乘,去做判断就行了,注意开long long
N N N阶乘指的是 1 ∗ 2 ∗ 3 ∗ 4.... ∗ N 1*2*3*4....*N 1∗2∗3∗4....∗N
C - Snake Queue
首先要把题目读懂,意思就是有几个操作,放蛇进来,让最前面的蛇出去,以及查询第K条蛇的头是哪个位置。我们可以想象一下,蛇在一个无限长的数组内排队
我们用 h e a d head head 来记录当前还在排队的蛇,所在数组的哪个位置,用 t a i l tail tail记录最后一条蛇在数组的哪个位置。如果接下来有新的蛇来排队,那么我们 t a i l + + tail++ tail++ 开辟一个新的位置,让新来的蛇排队进去。如果最前面的蛇要出去,我们就让 h e a d + + head++ head++ 这样子始终能保证数组中下标为 h e a d 到 t a i l head到tail head到tail 位置就是还在排队的蛇。
题目想问,当前在排队的第K条蛇的头位置在哪?
根据刚刚画的图, A [ h e a d ] 到 A [ t a i l ] A[head]到A[tail] A[head]到A[tail] 就是排队的蛇,所以第 K K K条蛇就在 A [ h e a d + K − 1 ] A[head+K-1] A[head+K−1]
现在要算它的头位置,其实就是算它前面所有还在排队的蛇的总长度
所以我们只需要计算历史以来,所有蛇的一个长度前缀和,以及所有出去的蛇的长度,相减就能得到目前我们排队中的蛇的长度。由于对于排队中第 K K K条蛇的头坐标其实是前一条蛇的尾巴,所以我们要去算 s u m [ h e a d + K − 1 − 1 ] − p r e sum[head+K-1 -1 ] - pre sum[head+K−1−1]−pre , p r e pre pre 表示历史出去的蛇的总长度
#include<bits/stdc++.h>
using namespace std;
long long int sum[300010];//前缀和
int A[300010];
int main(){int q;cin>>q;int head=1;int tail=0;long long int pre=0;while(q--){int op;cin>>op;if(op==1){int len;cin>>len;A[++tail] =len;//加sum[tail]=sum[tail-1]+len; } else if(op==2){pre=pre+A[head];head++;} else{int pos;cin>>pos;cout<<sum[head+pos-2]-pre<<'\n'; } }return 0;
}
D - ?UPC
太简单了
E - Heavy Snake
直接枚举增加的量,然后把数组重新算一次,排序输出最大值就行了
#include<bits/stdc++.h>
using namespace std;
int lon[1000];
int hea[1000];
int main(){int n,m;cin>>n>>m;for(int i=1;i<=n;i++)cin>>hea[i]>>lon[i];for(int o=1;o<=m;o++){int maxn=0;for(int i=1;i<=n;i++){maxn=max(maxn,(lon[i]+o)*hea[i]);}cout<<maxn<<'\n';}return 0;
}
F - Various Kagamimochi
这是一个经典的二分查找某个数值第一次出现的位置的问题
#include<bits/stdc++.h>
using namespace std;
int A[100];
int main() {int n;cin>>n;//1 2 3 3 3 4 5 6for(int i=1; i<=n; i++) {cin>>A[i];}int L=1,R=n; // L R的初始值 是你的答案可能的区间 int m=3;
//假设m就是我们要找的目标数字while(L<R) {int mid=(L+R)/2;//取一半,来划分 if(A[mid]>=m) {// [L mid R] 为了寻找更靠前的解 区间应该缩小 R=midR=mid;} else {L=mid+1;//A[mid]<m }}if(A[R]==m)cout<<R;else cout<<"无解";return 0;
}// 寻找最小的可能答案 有N 1e5 个糍粑 每个糍粑宽度是A[i]
两个不同的糍粑可以叠在一起 但 要满足 上面的糍粑至多只能为另一个糍粑的一半
题目想问,有多少种不同的糍粑叠起来的方案暴力
int ans=0;
for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){//假设i糍粑是上面的,j糍粑是下面的 if(A[i]*2<=A[j])ans++;}
}
n*n=1e10先对糍粑排序 从小到大 对于i糍粑,如果我知道了它合适的糍粑的第一个位置j
因为所有糍粑的大小已经排序了, [j,n] 这些糍粑 是不是都可以跟i 叠起来
问题变为: 对于每个糍粑i 寻找第一个>=2*A[i] 的位置
糍粑不是排序 二分一次 Nlog(N) 1e5*20 2e6 [i+1 N] int L=i+1,R=N;while(L<R){int mid=(L+R)/2;if(A[mid]>=2*A[i]){// [L mid R] R=mid; }else{// 意味着A[mid]<2*A[i] L=mid+1; }}if(A[R]>=2*A[i]) {//[R~N] ans+=N-R+1;}
答案代码如下
#include<bits/stdc++.h>
using namespace std;
const int MAXN=5e6+10;
long long int a[MAXN];
int n;
int main(){cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}long long int ans=0;for(int i=1;i<n;i++){int l=i+1,r=n;while(l<r){long long int mid=(l+r)/2;if(a[mid]>=a[i]*2)r=mid;else l=mid+1;}if(a[r]>=2*a[i]){ans=ans+n-r+1; }}cout<<ans; return 0;
}
G题H题没什么好说的,自己想