Codeforces Round #695 (Div. 2)
原题链接:https://codeforces.com/contest/1467
A. Wizard of Orz
A题就WA了两发才过,真是令人难受
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int main() { int t,n; cin>>t; while(t--) { cin>>n; int k=9; while(n--) { cout<<k; k-=1; if(k==-1) k=9; } cout<<endl; } return 0; }
B. Hills And Valleys
B题自己写模拟写的心态爆炸,道理很简单,就是写不对,最后还是大佬的题解思路清晰
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=3e5+10; int a[maxn]; int n; int f(int x) { if(x==1||x==n) return 0; if(a[x-1]<a[x]&&a[x+1]<a[x]) return 1; if(a[x-1]>a[x]&&a[x+1]>a[x]) return 1; return 0; } int main() { int t; cin>>t; while(t--) { cin>>n; memset(a,0,sizeof(a)); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int ans=0; for(int i=2;i<n;i++) { if(a[i-1]<a[i]&&a[i+1]<a[i]) ans++; if(a[i-1]>a[i]&&a[i+1]>a[i]) ans++; } int sum=0; for(int i=2;i<n;i++) { int flag=a[i]; int ans1=f(i-1)+f(i)+f(i+1); a[i]=a[i-1]; int ans2=f(i-1)+f(i)+f(i+1); a[i]=a[i+1]; int ans3=f(i-1)+f(i)+f(i+1); a[i]=flag; sum=max(sum,max(ans1-ans2,ans1-ans3)); } cout<<max(0,ans-sum)<<endl; } return 0; }
C. Three Bags
题意:有三个背包,里面各自装了数, 每次可以选择任意两个非空背包,取其中一个数a和b 然后变成a-b放回 a背包中,b背包中的该数消失 直到最后只剩下一个数, 问剩下的数最大为多少
思路:考虑最后所有的数都会归到一个数的身上,这个数给的贡献不是正数就是负数,取决于中间走了几步
奇数为负数,偶数为正数, 所有最后的答案是总的sum-2*sub , ×2是为了抵消掉负数加进去sum的贡献
那么就只有几种情况:
要么是某两个背包的最小的数来作为跳板
要么是只用某一个背包的最小数来作为跳板变成正数,然后这一个背包的数 全部当作负数贡献
#include<iostream> #include<cstdio> #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=3e5+10; int a[maxn],b[maxn],c[maxn]; ll d[10]; int main() { int n1,n2,n3; ll sum1=0,sum2=0,sum3=0; cin>>n1>>n2>>n3; for(int i=1;i<=n1;i++) scanf("%d",&a[i]),sum1+=a[i],a[1]=min(a[i],a[1]); for(int i=1;i<=n2;i++) scanf("%d",&b[i]),sum2+=b[i],b[1]=min(b[i],b[1]); for(int i=1;i<=n3;i++) scanf("%d",&c[i]),sum3+=c[i],c[1]=min(c[i],c[1]); ll ans=sum1+sum2+sum3; ll flag=1e17; d[1]=flag; d[2]=sum1; d[3]=sum2; d[4]=sum3; d[5]=a[1]+b[1]; d[6]=a[1]+c[1]; d[7]=b[1]+c[1]; for(int i=1;i<=7;i++) d[1]=min(d[i],d[1]); cout<<ans-2*d[1]<<endl; return 0; }
D. Sum of Paths
先预处理出所有走法每个格子会被走的次数总和
dp[i][j]dp[i][j] 表示第 j步走到第 i个格子的情况数量
初始化 dp[i][0]=1
转移方程 d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + d p [ i + 1 ] [ j − 1 ] ,即通过一步从相邻格子转移来;
那么走 j步恰好到达第 i 个格子的情况数为 d p [ i ] [ j ] ,但是一共要走 k 步
从第 i 个格子走 k − j 步的情况数量等于从任意格子走 k − j 步恰好到达第i 个格子的情况,即 d p [ i ] [ k − j ],所以次数贡献就是 d p [ i ] [ j ] ⋅ d p [ i ] [ k − j ]
知道每个格子的贡献次数,那么改变一个格子就可以 O ( 1 ) 算出了。
#include<iostream> #include<cstdio> using namespace std; typedef long long ll; const ll mod=1e9+7; const int maxn=5e3+10; ll a[maxn]; ll dp[maxn][maxn]; ll cnt[maxn]; int main() { int n,k,q; cin>>n>>k>>q; for(int i=1;i<=n;i++) scanf("%d",&a[i]),dp[i][0]=1; for(int j=1;j<=k;j++) for(int i=1;i<=n;i++) dp[i][j]=(dp[i-1][j-1]+dp[i+1][j-1])%mod; for(int j=0;j<=k;j++) for(int i=1;i<=n;i++) cnt[i]=(cnt[i]+dp[i][j]*dp[i][k-j])%mod; ll ans=0; for(int i=1;i<=n;i++) ans=(ans+cnt[i]*a[i])%mod; int id,x; while(q--) { scanf("%d%d",&id,&x); ans=(ans+(x-a[id]+mod)%mod*cnt[id])%mod; printf("%lld\n",ans); a[id]=x; } return 0; }

浙公网安备 33010602011771号