T1 辣鸡(ljh)
就是一道分类讨论的暴搜,外加一丢丢的减枝,然而我挂了,为啥呢,分类讨论变量名打错,大于小于号打反,能对才怪,写了sort为了调试就注释了,后来忘了解开,小减枝也没打。但是这道题做了2个小时不止,T2T3完全挤得没时间。做这道题只感觉心累。。。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define ll long long using namespace std; struct node { ll a,b,c,d,w; }q[100100]; ll n,ans,mr; bool cmp(node x,node y) {return x.a==y.a?x.b<y.b:x.a<y.a;} ll read() { ll aa=0,bb=1;char cc=getchar(); while(cc>'9'||cc<'0'){if(cc='-') bb=-1;cc=getchar();} while(cc<='9'&&cc>='0'){aa=aa*10+cc-'0';cc=getchar();} return aa*bb; } int main() { n=read(); for(ll i=1;i<=n;i++){ q[i].a=read(),q[i].b=read(),q[i].c=read(),q[i].d=read(); q[i].w=(q[i].c-q[i].a)*(q[i].d-q[i].b)*2; } sort(q+1,q+n+1,cmp); for(ll i=1;i<=n;i++){ ll a=q[i].a,b=q[i].b,c=q[i].c,d=q[i].d; ans+=q[i].w;mr=c; for(ll j=i+1;j<=n;j++){ ll x1=q[j].a,y1=q[j].b,x2=q[j].c,y2=q[j].d; if(x1>mr+1) break; mr=max(mr,x2); if(d==y1-1){ if(a<=x1&&x1<=c&&c<=x2){ ll chong=c-x1; ans+=chong*2; if(c<x2) ans++; if(a<x1) ans++; } else if(x1<=a&&a<=x2&&x2<=c){ ll chong=x2-a; ans+=chong*2; if(c>x2) ans++; if(x1<a) ans++; } else if(x1<=a&&a<=c&&c<=x2){ ll chong=c-a; ans+=chong*2; if(x1<a) ans++; if(c<x2) ans++; } else if(a<=x1&&x1<=x2&&x2<=c){ ll chong=x2-x1; ans+=chong*2; if(a<x1) ans++; if(x2<c) ans++; } else if(x2==a-1) ans++; else if(c==x1-1) ans++; } else if(y2==b-1){ if(x1<=a&&a<=x2&&x2<=c){ ll chong=x2-a; ans+=chong*2; if(x1<a) ans++; if(x2<c) ans++; } else if(a<=x1&&x1<=c&&c<=x2){ ll chong=c-x1; ans+=chong*2; if(c<x2) ans++; if(a<x1) ans++; } else if(a<=x1&&x1<=x2&&x2<=c){ ll chong=x2-x1; ans+=chong*2; if(x2<c) ans++; if(a<x1) ans++; } else if(x1<=a&&a<=c&&c<=x2){ ll chong=c-a; ans+=chong*2; if(c<x2) ans++; if(x1<a) ans++; } else if(x2==a-1) ans++; else if(c==x1-1) ans++; } else if(c==x1-1){ if(y1<=b&&b<=y2&&y2<=d){ ll chong=y2-b; ans+=chong*2; if(d>y2) ans++; if(b>y1) ans++; } else if(b<=y1&&y1<=d&&d<=y2){ ll chong=d-y1; ans+=chong*2; if(d<y2) ans++; if(b<y1) ans++; } else if(y1<=b&&b<=d&&d<=y2){ ll chong=d-b; ans+=chong*2; if(d<y2) ans++; if(b>y1) ans++; } else if(b<=y1&y1<=y2&&y2<=d){ ll chong=y2-y1; ans+=chong*2; if(y2<d) ans++; if(b<y1) ans++; } } else if(x2==a-1){ if(b<=y1&&y1<=d&&d<=y2){ ll chong=d-y1; ans+=chong*2; if(y2>d) ans++; if(y1>b) ans++; } else if(y1<=b&&b<=y2&&y2<=d){ ll chong=y2-b; ans+=chong*2; if(d>y2) ans++; if(b>y1) ans++; } else if(y1<=b&&b<=d&&d<=y2){ ll chong=d-b; ans+=chong*2; if(d<y2) ans++; if(y1<b) ans++; } else if(b<=y1&y1<=y2&&y2<=d){ ll chong=y2-y1; ans+=chong*2; if(d>y2) ans++; if(b<y1) ans++; } } } } printf("%lld\n",ans); }
T2 模板(ac)
前30分暴力往上翻(dfs往下找也可以,时间稍长),中间40分雨天的尾巴线段树动态开点+线段树合并(考试压根没看见这40分的情况,数据范围一定要看的不),最后30分暂时还没看懂,先留着。
#include<iostream> #include<cstdio> #include<cstring> #include<map> #define ll long long #define MAX 100100 using namespace std; struct node { ll to,nxt; }t[MAX*4]; struct tree { ll l,r,sum; }h[MAX*20]; ll n,m,q,tot,cnt,nxt[MAX*4],w[MAX],a[10010][10010],ans[MAX],fa[MAX]; ll root[MAX],num; map<ll,ll>mp; bool vis[MAX],vv[10010][10010],flag; ll read() { ll aa=0,bb=1;char cc=getchar(); while(cc>'9'||cc<'0'){if(cc=='-') bb=-1;cc=getchar();} while(cc<='9'&&cc>='0'){aa=aa*10+cc-'0';cc=getchar();} return aa*bb; } void add(ll x,ll y) { t[++tot].to=y; t[tot].nxt=nxt[x]; nxt[x]=tot; } void dfs(ll x) { for(ll i=nxt[x];i;i=t[i].nxt){ ll y=t[i].to; if(vis[y]) continue; vis[y]=1; fa[y]=x; dfs(y); } } void find(ll x,ll c) { while(x!=0){ if(w[x]){ w[x]--; if(!vv[x][c]){ vv[x][c]=1; ans[x]++; } } x=fa[x]; } } void update(ll x) { h[x].sum=h[h[x].l].sum+h[h[x].r].sum; } void insert(ll &rt,ll l,ll r,ll pos) { if(!rt) rt=++num; if(l==r){ h[rt].sum=1; return; } ll mid=(l+r)>>1; if(pos<=mid) insert(h[rt].l,l,mid,pos); else insert(h[rt].r,mid+1,r,pos); update(rt); } ll merge(ll x,ll y,ll l,ll r) { if(!x||!y) return x+y; if(l==r) return x; ll mid=(l+r)>>1; h[x].l=merge(h[x].l,h[y].l,l,mid); h[x].r=merge(h[x].r,h[y].r,mid+1,r); update(x); return x; } void Dfs(ll x) { for(ll i=nxt[x];i;i=t[i].nxt){ ll y=t[i].to; if(vis[y]) continue; vis[y]=1; Dfs(y); root[x]=merge(root[x],root[y],1,m); } ans[x]=h[root[x]].sum; } int main() { n=read(); ll u,v; for(ll i=1;i<n;i++){ u=read();v=read(); add(u,v); add(v,u); } for(ll i=1;i<=n;i++){ w[i]=read(); if(w[i]!=100000) flag=1; } if(n<=1000){ vis[1]=1; dfs(1); m=read(); for(ll i=1,x,c;i<=m;i++){ x=read();c=read(); if(!mp[c]) mp[c]=++cnt; find(x,mp[c]); } q=read(); for(ll i=1,x;i<=q;i++){ x=read(); printf("%lld\n",ans[x]); } return 0; } if(!flag){ m=read(); for(ll i=1,x,c;i<=m;i++){ x=read();c=read(); if(!mp[c]) mp[c]=++cnt; insert(root[x],1,m,mp[c]); } vis[1]=1; Dfs(1); q=read(); for(ll i=1,x;i<=q;i++){ x=read(); printf("%lld\n",ans[x]); } return 0; } }
T3 大佬(kat)
概率与期望,看了眼题就跑了,但据大佬们说“这是道水题”,“这是最简单的题”,“我30分钟看题+ac”(都是神仙)。(我确实是不会)考试看题都看错了。。。
这是一道假期望。。。
f[i][j]表示前i道题,最大难度为j的方案数,两种情况转移:1.第j道题的难度是j。所以前面的题难度只要不大于j就可以(看题看题看题),f[i][j]=Σf[i-1][l] (l<j);2.第i题的难度小于j,那么前i-1题里就必须要有j难度的,且第i题有j种选择方案即(1~j-1),f[i][j]=f[i-1][j]*j,转移就行。这n道题,可以做(n-k+1)天,这(n-k+1)天是相对独立的,所以求出的方案数×天数就是合法方案数,总的方案数就是mk,乘上代价就是期望。
#include<iostream> #include<cstdio> #define ll long long #define mod 1000000007 using namespace std; ll n,m,k,w[510],f[510][510],up,down; ll quick(ll x,ll p) { ll ans=1; while(p){ if(p&1) ans=ans*x%mod; x=x*x%mod; p>>=1; } return ans%mod; } int main() { scanf("%lld%lld%lld",&n,&m,&k); for(ll i=1;i<=m;i++) scanf("%lld",&w[i]); if(k>n){ puts("0"); return 0; } for(ll i=1;i<=m;i++) f[1][i]=1; for(ll i=2;i<=k;i++){ for(ll j=1;j<=m;j++){ (f[i][j]+=f[i-1][j]*j)%=mod; for(ll l=1;l<j;l++) (f[i][j]+=f[i-1][l])%=mod; } } for(ll i=1;i<=m;i++) (up+=f[k][i]*w[i]%mod)%=mod; down=quick(m,k);down=quick(down,mod-2); printf("%lld\n",up*down%mod*(n-k+1)%mod); }