https://codeforces.com/contest/1084
A题
数据量很小,枚举就行
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<map> 5 #include<vector> 6 #include<cmath> 7 #include<algorithm> 8 using namespace std; 9 typedef long long ll; 10 int qwq[105]; 11 int main(){ 12 // freopen("in.txt","r",stdin); 13 int n; 14 cin>>n; 15 for(int i=1;i<=n;i++){ 16 scanf("%d",&qwq[i]); 17 } 18 int ans=0x3f3f3f3f; 19 for(int i=1;i<=n;i++){ 20 int xx=0; 21 for(int j=1;j<=n;j++){ 22 xx+=2*(abs(j-i)+(i-1)+(j-1))*qwq[j]; 23 } 24 ans=min(xx,ans); 25 } 26 cout << ans<<endl; 27 return 0; 28 }
B题
二分,只要不犯sb错就行(然而我犯sb错fst了 #微笑#)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<map> 5 #include<vector> 6 #include<cmath> 7 #include<algorithm> 8 using namespace std; 9 typedef long long ll; 10 ll qwq[1005],n,k; 11 bool check(ll x){ 12 ll sums=0; 13 for(int i=0;i<n;i++){ 14 if(qwq[i]<x)return false; 15 else sums+=qwq[i]-x; 16 } if(sums>=k)return true; 17 return false; 18 } 19 int main(){ 20 // freopen("in.txt","r",stdin); 21 //ll n,k; 22 cin>>n>>k; 23 ll sum=0; 24 for(int i=0;i<n;i++){ 25 scanf("%lld",&qwq[i]); 26 sum+=qwq[i]; 27 } 28 if(sum<k){printf("-1 ");return 0;} 29 ll l=0; 30 ll r=1e9+2; 31 while(l<=r){ 32 ll mid=(l+r)/2; 33 if(check(mid))l=mid+1; 34 else r=mid-1; 35 } 36 while(check(l+1))l++; 37 while(!check(l))l--; 38 cout << l << endl; 39 return 0; 40 }
C题
题意:给一个字符串,求有多少个子序列满足:元素都为a,并且如果元素个数>1,那么在原序列中每个a之间必须至少有一个b.
题解:无视除a,b之外的别的字母,用b把a分成若干部分,设第i部分的a的个数是 ai ,那么这个部分的取法有 (ai+1)种(即不取,或者从中选一个)但是最后要防止所有部分不取,即ans=(a1+1)*(a2+1)*,,,*(ax+1) -1 .
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<map> 5 #include<vector> 6 #include<cmath> 7 #include<algorithm> 8 using namespace std; 9 typedef long long ll; 10 const ll mod=1e9+7; 11 char ch[100005]; 12 int qwq[100005],qaq[100005]; 13 ll mypow(ll x,ll y){ 14 ll ans=1; 15 while(y){ 16 if(y&1)ans=(ans%mod)*(x%mod)%mod; 17 x=(x%mod)*(x%mod)%mod; 18 y/=2; 19 } 20 return ans; 21 } 22 int main(){ 23 //freopen("in.txt","r",stdin); 24 scanf("%s",ch); 25 int len=strlen(ch); 26 ll tot=0; 27 ll tot2=0; 28 ll tot3=0; 29 ll tot4=0; 30 ll ans=1; 31 for(int i=0;i<len;i++){ 32 if(ch[i]=='a'){if(tot3){qaq[tot4]=tot3;tot3=0;tot4++;}tot2++;} 33 else if(ch[i]=='b'){ 34 if(tot2){ 35 qwq[tot]=tot2; 36 tot2=0; 37 tot++; 38 } 39 if(tot)tot3++; 40 } 41 }if(tot2)qwq[tot++]=tot2; 42 for(int i=0;i<tot;i++){ 43 ans=(ans%mod)*((qwq[i]+1)%mod)%mod; 44 } 45 cout << ans-1<<endl; 46 return 0; 47 }
D题
题意:给一棵树,求一条链顶点的权值和 - 边的权值和的最大值
题解:开两个dp数组,一个数组记录从根出发到当前结点得到的最大值,另一个数组记录从该点遍历到尽头回溯得到的最大值(这就很好的解决了到底应该从哪个点开始dfs的问题..因为一边递归过程dp,一边回溯过程dp可以确保得到的一定是最优解)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<map> 5 #include<vector> 6 #include<cmath> 7 #include<algorithm> 8 using namespace std; 9 typedef long long ll; 10 int n; 11 ll ans=0; 12 int head[300005]; 13 ll qwq[300005]; 14 struct edge{ 15 int u; 16 int v; 17 ll val; 18 int nex; 19 }e[600005]; 20 int cnt; 21 ll dp[300004],dp2[300004]; 22 bool vis[300005]; 23 void add(int x,int y,ll z){ 24 e[cnt].u=x; 25 e[cnt].v=y; 26 e[cnt].val=z; 27 e[cnt].nex=head[x]; 28 head[x]=cnt++; 29 } 30 void dfs(int x){ 31 vis[x]=1; 32 for(int i=head[x];i!=-1;i=e[i].nex){ 33 int v=e[i].v; 34 if(vis[v])continue; 35 dp[v]=max(qwq[v],qwq[v]+dp[x]-e[i].val); 36 dfs(v); 37 dp2[x]=max(dp2[x],dp2[v]+qwq[x]-e[i].val); 38 dp[x]=max(dp2[x],dp[x]); 39 } 40 dp2[x]=max(dp2[x],qwq[x]); 41 dp[x]=max(dp[x],dp2[x]); 42 ans=max(dp[x],ans); 43 } 44 int main(){ 45 // freopen("in.txt","r",stdin); 46 cin>>n; 47 for(int i=1;i<=n;i++){ 48 scanf("%lld",&qwq[i]); 49 } 50 memset(head,-1,sizeof(head)); 51 for(int i=0;i<n-1;i++){ 52 int a,b; 53 ll c; 54 scanf("%d%d%lld",&a,&b,&c); 55 add(a,b,c); 56 add(b,a,c); 57 } 58 dfs(1); 59 printf("%lld ",ans); 60 return 0; 61 }