10.22考试反思
作者:互联网
Contest2208 - 2019年10月多校联训B层测试13
T1 友善的D题
http://www.accoders.com/problem.php?cid=2208&pid=0
我们首先看到这道题,乘积最大,首先想到必定为正,然后,考虑什么情况能一定是正数,一定是偶数个负数相乘和任意个整数相乘得到的,我们考虑如何能让答案最大,负数*-1-1答案会变小,我们就可以 贪心的让先让所有的数都是负数,然后看n是不是偶数,如果不是偶数,就把这些负数里面最小的(绝对值最大的那个拿出来,变成正数)具体证明如下
设当前序列的最大值为a,最小值为b,现在负数积为ans
1.拿走a的时候 答案变为ans/a*(-a-1);化简得ans-ans/abs(a); 拿走b的时候同理ans-ans/abs(b),因为b的绝对值大于a的绝对值,所以拿走最大值的时候答案优,证毕
#include <bits/stdc++.h> #define ll long long #define res register #define MAXN 100050 #define int ll using namespace std; int n,maxn,a[MAXN]; ll read() { int s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-48;ch=getchar();} return s*w; } signed main() { n=read(); for(res int i=1;i<=n;i++) a[i]=read(),a[i]=a[i]>=0?-a[i]-1:a[i],maxn=max(maxn,abs(a[i])); if(n&1) for(res int i=1;i<=n;i++) if(a[i]==-maxn) {a[i]=-a[i]-1;break;} for(res int i=1;i<=n;i++) cout<<a[i]<<" "; return 0; }View Code
T2 友善的E题
http://www.accoders.com/problem.php?cid=2208&pid=1
预处理出0与1的前缀和,由于每次取走一个数后剩余区间会越来越短,所以先取大的(也就是原序列中为1的)再取小的,设l-r区间中1出现次数为c1,0出现的次数为c2,答案就是(2^c1-1)* 2 ^c2,预处理出2的次幂即可。
#include <bits/stdc++.h> #define ll long long #define res register #define MAXN 100500 #define int ll #define mo 1000000007 using namespace std; int n,m,l,r,sum[MAXN],kc[MAXN]; char a[MAXN]; bool vis[MAXN]; ll read() { int s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-48;ch=getchar();} return s*w; } signed main() { n=read(),m=read();kc[1]=1; for(res int i=2;i<=100005;i++) kc[i]=((kc[i-1]<<1))%mo; cin>>a+1; for(res int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]-'0'; while(m--){ l=read(),r=read(); int summ=sum[r]-sum[l-1]; int length=r-l+1; int zero=length-summ; int one=length-zero; int q1=(kc[one+1]-1)*(kc[zero+1])%mo; printf("%lld\n",q1); } return 0; }View Code
T3. 友善的F题
http://www.accoders.com/problem.php?cid=2208&pid=2
#include <bits/stdc++.h> #define ll long long #define res register #define MAXN 1000500 #define mo 1000000007 #define int ll using namespace std; int head[MAXN],n,m,x,y,z,ans[3],dp[MAXN][3],siz[MAXN]; bool vis[MAXN]; struct Node{ int to,nxt,dis,sum[3],exist[3]; }g[MAXN]; inline void dfs(int u){ vis[u]=1;int to=g[u].to,dis=g[u].dis; for(res int i=head[to];i;i=g[i].nxt){ if(i==(u^1)) continue; if(!vis[i]) dfs(i); for(res int j=0;j<=2;j++){ if(!g[i].exist[j]) continue; g[u].exist[(dis+j)%3]+=g[i].exist[j]; g[u].sum[(dis+j)%3]=(g[u].sum[(dis+j)%3]+dis*g[i].exist[j]+g[i].sum[j])%mo; } } } inline void add(int u,int v,int dis){ static int top=1; g[++top].to=v;g[top].nxt=head[u];g[top].sum[dis%3]=dis; g[top].exist[dis%3]=1;g[top].dis=dis;head[u]=top; } ll read() { int s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-48;ch=getchar();} return s*w; } signed main() { n=read(); for(res int i=1;i<n;i++){ x=read()+1,y=read()+1,z=read(); add(x,y,z),add(y,x,z); } for(res int i=2;i<n*2;i++) { if(!vis[i]) dfs(i); for(res int j=0;j<=2;j++) ans[j]=(ans[j]+g[i].sum[j])%mo; } for(res int i=0;i<=2;i++) cout<<ans[i]<<" "; return 0; }View Code
对于50%的数据,v的长度都是3的倍数,也就是说我们只统计地图1的数据就可以了,对于每个节点处理一个f数组,表示着子节点中所有的点到当前点的路径总和,对于当前的节点的每一个子节点,在递归时处理一下与之前节点的总路径长度并且加到答案里,遍历一遍树的同时就可以统计出答案。
对于100%的数据,就维护三个数组,数组之间在统计答案的同时判断一下要处理到哪个数组里去
标签:10.22,ch,int,res,ll,MAXN,反思,考试,define 来源: https://www.cnblogs.com/Lbmttw/p/11842641.html