AtCoder Beginner Contest 159
A - The Number of Even Pairs
#include <bits/stdc++.h> #define ll long long using namespace std; int main() { //freopen("in.txt","r",stdin); int n,m; scanf("%d%d",&n,&m); printf("%d\n",n*(n-1)/2+m*(m-1)/2); return 0; }
B - String Palindrome
#include <bits/stdc++.h> #define ll long long using namespace std; char s[105]; bool cal(int l,int r) { for(int i=l;i<=r;i++) { if(s[i]!=s[r+l-i]) return false; } return true; } int main() { //freopen("in.txt","r",stdin); scanf("%s",s+1); int n=strlen(s+1); bool f=true; if(!cal(1,n)) f=false; if(!cal(1,(n-1)/2)) f=false; if(!cal((n+3)/2,n)) f=false; printf("%s\n",f?"Yes":"No"); return 0; }
C - Maximum Volume
题意:已知长方体的长+宽+高等于L,求长方体的最大体积。
数据范围:$1 \leq L \leq 1000$
题解:长方体最大体积时,长=宽=高=L/3。
#include <bits/stdc++.h> #define ll long long using namespace std; int main() { //freopen("in.txt","r",stdin); double L; scanf("%lf",&L),L/=3; printf("%.12f\n",L*L*L); return 0; }
D - Banned K
题意:给N个球,每个球上有数字Ai,求去掉第i个球以后,选两个相同数字的球的方案数。
数据范围:$3 \leq N \leq 2 \times 10^{5},1 \leq A_{i} \leq N$
题解:先算出不去掉任何球的方案数,即为每个数字个数中取两个的组合数总和。
去掉第i个球,先减去该球上sum[Ai]对答案的贡献,然后加上C(sum[Ai]-1,2)。
#include <bits/stdc++.h> #define ll long long using namespace std; const int N=2e5+5; int a[N],num[N]; int main() { //freopen("in.txt","r",stdin); int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); num[a[i]]++; } ll ans=0; for(int i=1;i<=n;i++) { ans+=1LL*num[i]*(num[i]-1)/2; } for(int i=1;i<=n;i++) { ans-=1LL*num[a[i]]*(num[a[i]]-1)/2; num[a[i]]--; printf("%lld\n",ans+1LL*num[a[i]]*(num[a[i]]-1)/2); num[a[i]]++; ans+=1LL*num[a[i]]*(num[a[i]]-1)/2; } return 0; }
E - Dividing Chocolate
题意:给一个H*W的矩阵,其中’0‘代表该点为黑,’1‘代表该点为白,可以进行横着或竖着切,求至少切几次满足每块的白块不超过K块。
数据范围:$1 \leq H \leq 10,1\leq W \leq 1000,1 \leq K \leq H \times W$
题解:由于H很小,可以枚举横着切的情况,然后就是枚举每列求最小次数。
#include <bits/stdc++.h> using namespace std; const int N=1e3+5; char s[15][N]; int a[15][N]; int cal(int x1,int x2,int y) { int ans=0; for(int i=x1;i<=x2;i++) { ans+=(s[i][y]=='1'); } return ans; } int main() { //freopen("in.txt","r",stdin); int n,m,k; scanf("%d%d%d",&n,&m,&k); for(int i=0;i<n;i++) { scanf("%s",s[i]); } int ans=1e9; for(int s=0;s<(1<<(n-1));s++) { vector<int> vec; vec.push_back(-1); for(int i=0;i<n-1;i++) { if((1<<i)&s) vec.push_back(i); } vec.push_back(n-1); int sz=vec.size(); bool f=true; for(int j=0;j<m;j++) { for(int i=1;i<sz;i++) { a[i][j]=cal(vec[i-1]+1,vec[i],j); if(a[i][j]>k) f=false; } } if(!f) continue; int num=0,b[15]={0}; for(int j=0;j<m;j++) { bool f=true; for(int i=1;i<sz;i++) { b[i]+=a[i][j]; if(b[i]>k) f=false; } if(!f) { num++; for(int i=1;i<sz;i++) { b[i]=a[i][j]; } } } ans=min(ans,sz-2+num); } printf("%d\n",ans); return 0; }
F - Knapsack for All Segments
题意:给一个长度为N的序列A,定义f(L,R)为AL~AR中子序列总和为S的方案数,求$\sum_{L=1}^{N} \sum_{R=L}^{N} f(L,R) $(对998244353取模)。
数据范围:$1 \leq N,S,A_{i} \leq 3000$
题解:通过朴素的01背包可以求出1~[1,N]的所有数,然后需要求2~[2,N]、3~[3,N]的总和,可以在第i个位置加一个起点,也就是f[0]++,这样就能合并在一起。
#include <bits/stdc++.h> #define ll long long using namespace std; const int N=3e3+5; const int MD=998244353; int a[N],f[N]; void add(int &x,int y) { x+=y; if(x>=MD) x-=MD; } int main() { //freopen("in.txt","r",stdin); int n,s; scanf("%d%d",&n,&s); for(int i=0;i<n;i++) { scanf("%d",&a[i]); } int ans=0; for(int i=0;i<n;i++) { add(f[0],1); for(int j=s;j>=a[i];j--) { add(f[j],f[j-a[i]]); } add(ans,f[s]); } printf("%d\n",ans); return 0; }