男人八题 划水题解
T1 生物
根据题意存储每个数并进行模拟即可
#include<cstdio> #define int long long using namespace std; int num[100010],a[100010]; signed main() { //freopen("biology.in","r",stdin); //freopen("biology.out","w",stdout); int k; scanf("%d",&k); a[0]=1; for(int i=1;i<=k;i++) { if(i%2==0) a[i]=i/2+1; else a[i]=1; } num[0]=1; for(int i=1;i<=k;i++) { num[i]=num[i-1]+a[i]; } printf("%lld",num[k-1]); return 0; }
T2 化学
不难发现中间的数n种取法都可以
对角的数两两差为a-d,b-c,d-a,c-b
极差即为abs(a-d)+abs(b-c)
固定一个数为基,即可做到不重复
最后乘上n即可
#include<cstdio> #include<cmath> #define int long long using namespace std; signed main() { //freopen("chemistry.in","r",stdin); //freopen("chemistry.out","w",stdout); int n; scanf("%lld",&n); int a,b,c,d; scanf("%lld%lld%lld%lld",&a,&b,&c,&d); int ans=(n-abs(a-d)-abs(b-c))*n; printf("%lld",ans); return 0; }
T3 语文
在1~n放数,会产生1~i-1的贡献
dp[i][j]表示前i个数j的贡献
因为dp[i][j]=sum_{dp[i-1][j-k]}(k=0 -> i-1)
不难看出可以用前缀和优化
最后O(n*k)
#include<cstdio> #include<cctype> using namespace std; const int mod=998244353; int sum[5050][5050]; int dp[5050][5050]; int read() { int f=1,x=0; char ch=' '; for(;!isdigit(ch);ch=getchar())if(ch=='-')f*=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return f*x; } int main() { int n,m; n=read(); m=read(); dp[0][0]=1; for(int i=0;i<=m;i++) sum[0][i]=1; for(int i=1;i<=n;i++) { for(int j=0;j<=m;j++) { if(i<=j) dp[i][j]=((dp[i][j]+sum[i-1][j])%mod-sum[i-1][j-i]+mod)%mod; else dp[i][j]=(dp[i][j]+sum[i-1][j])%mod; if(!j) sum[i][j]=dp[i][j]; else sum[i][j]=(sum[i][j-1]+dp[i][j])%mod; } } printf("%lld\n",dp[n][m]); return 0; }
T4 英语
仅使用01可以推出,最靠近中点的能使中位数出现相邻两数相等的那组数便是最终解
画图可以得知符合二分性
则直接2分顶点即可
#include<cstdio> #include<cctype> #include<algorithm> using namespace std; int a[1000010]; int n; int read() { int f=1,x=0; char ch=' '; for(;!isdigit(ch);ch=getchar())if(ch=='-')f*=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return f*x; } int check(int x) { for(int i=0;i<=n-2;i++) { if((a[n-i-1]>=x)==(a[n-i]>=x)) return a[n-i-1]>=x; if((a[n+i+1]>=x)==(a[n+i]>=x)) return a[n+i+1]>=x; } return a[1]>=x; } int main() { n=read(); int mmax=1; for(int i=1;i<=n*2-1;i++) { a[i]=read(); mmax=max(mmax,a[i]); } int l=1,r=mmax; int ans=1; while(l<=r) { int mid=(l+r)/2; if(check(mid)) l=mid+1,ans=mid; else r=mid-1; } printf("%d",ans); }
T5 地理
考虑维护两个树状数组
l中的<=R的减去r中<=L的即可
#include<cstdio> #define lowbit(x) x&(-x) #define int long long using namespace std; int n; struct Node { int a[200010]; void add(int x) { while(x<=n) { a[x]++; x+=lowbit(x); } } int count(int x) { int sum=0; while(x!=0) { sum+=a[x]; x-=lowbit(x); } return sum; } }; Node ans1,ans2; signed main() { scanf("%lld",&n); for(int i=1;i<=n;i++) { int opt; scanf("%lld",&opt); if(opt==1) { int l,r; scanf("%lld%lld",&l,&r); ans1.add(l); ans2.add(r); } else { int l,r; scanf("%lld%lld",&l,&r); int ans=ans1.count(r)-ans2.count(l-1); //printf("%d %d \n",ans1.count(r),ans2.count(l-1)); printf("%lld\n",ans); } } }
T6 历史
在前pi-1个数中记录每个数出现次数
并维护整个序列最大值
每进来一个数只判断是否大于这个最大值即可
大于即选取,反之选取原有值,并将这个数放入序列
#include<cstdio> #include<cctype> using namespace std; int a[1000010],num[1000010]; int read() { int f=1,x=0; char ch=' '; for(;!isdigit(ch);ch=getchar())if(ch=='-')f*=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return f*x; } int main() { //freopen("history_2.in","r",stdin); //freopen("history.out","w",stdout); int n=read(); for(int i=1;i<=n;i++) a[i]=read(); int t=read(); while(t--) { int p=read(); int ans1=0,ans2=0; for(int i=1;i<p;i++) num[a[i]]++; int pos=n; for(int i=p;i<=n;i++) { int opt; if(a[i]>=pos) opt=a[i]; else { num[a[i]]++; while(!num[pos]&&pos) pos--; num[pos]--; opt=pos; } if((i-p+1)%2) ans1+=opt; else ans2+=opt; } for(int i=1;i<p;i++) { int opt; while(!num[pos]&&pos) pos--; num[pos]--; opt=pos; if((i+(n-p+1))%2) ans1+=opt; else ans2+=opt; } printf("%d\n",ans1-ans2); } return 0; }
T7,8由于太菜无法写出QAQ