T1
不太难的一个真暴力,考试想的太复杂了,总觉得直接枚举块不现实,就进行了一大堆多余的处理,结果是三个半小时把自己搞到了崩溃,非常崩溃,结果自暴自弃了?打题的时候还好吧,一直在改,现在想想还不如重构,考后一个小时多一点就A掉了
就是个大暴力,分情况讨论,计算块与块之间的贡献就可以了,块内直接算没问题
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #define maxn 100100 5 #define ll long long 6 #define int long long 7 using namespace std; 8 struct tj{ 9 ll qx,qy,zx,zy; 10 }a[maxn]; 11 int n; 12 ll ans; 13 bool cmp(const tj &a,const tj &b) 14 { 15 if(a.qx!=b.qx) return a.qx<b.qx; 16 if(a.qy!=b.qy) return a.qy<b.qy; 17 if(a.zx!=b.zx) return a.zx<b.zx; 18 return a.zy<b.zy; 19 } 20 signed main() 21 { 22 scanf("%lld",&n); 23 for(int i=1;i<=n;++i) 24 { 25 scanf("%lld%lld%lld%lld",&a[i].qx,&a[i].qy,&a[i].zx,&a[i].zy); 26 ans+=(a[i].zx-a[i].qx)*(a[i].zy-a[i].qy)*1ll*2; 27 } 28 sort(a+1,a+n+1,cmp); 29 for(int i=1;i<=n;++i) 30 { 31 for(int j=i+1;j<=n;++j) 32 { 33 if(a[j].qx>a[i].zx+1) break; 34 if(a[j].qy>a[i].zy+1||a[j].zy+1<a[i].qy) continue; 35 if(a[j].qy==a[i].zy+1) 36 { 37 int ls1=min(a[i].zx,a[j].zx),ls2=max(a[i].qx,a[j].qx); 38 ans+=(ls1-ls2)*2; 39 if(a[i].qx!=a[j].qx) ans++; 40 if(a[i].zx!=a[j].zx) ans++; 41 if(ls2-ls1==1) ans++; 42 } 43 else if(a[j].qx==a[i].zx+1) 44 { 45 int ls1=min(a[i].zy,a[j].zy),ls2=max(a[i].qy,a[j].qy); 46 ans+=(ls1-ls2)*2; 47 if(a[i].qy!=a[j].qy) ans++; 48 if(a[i].zy!=a[j].zy) ans++; 49 if(ls2-ls1==1) ans++; 50 } 51 else if(a[j].zx+1==a[i].qx) 52 { 53 int ls1=min(a[i].zy,a[j].zy),ls2=max(a[i].qy,a[j].qy); 54 ans+=(ls1-ls2)*2; 55 if(a[i].qy!=a[j].qy) ans++; 56 if(a[i].zy!=a[j].zy) ans++; 57 if(ls2-ls1==1) ans++; 58 } 59 else if(a[j].zy+1==a[i].qy) 60 { 61 int ls1=min(a[i].zx,a[j].zx),ls2=max(a[i].qx,a[j].qx); 62 ans+=(ls1-ls2)*2; 63 if(a[i].qx!=a[j].qx) ans++; 64 if(a[i].zx!=a[j].zx) ans++; 65 if(ls2-ls1==1) ans++; 66 } 67 } 68 } 69 printf("%lld\n",ans); 70 return 0; 71 }
T2
看见T2的时候其实就已经有点崩了,觉得它和之前的雨天的尾巴有点像,想往那个方向去,发现是个死胡同,怎么走都走不通,而且其实认定了自己线段树合并在考场上搞不出来,然后就弃掉了
刚才他们说这道题暴力+雨天的尾巴可以70分,我准备有时间搞一搞,正解估计又要留坑了
T3
这场考试最遗憾的一道题,最近看见概率与期望就想逃,需要重点练一练,这道其实不难,基本应该是可以想到,当然考场上我也不知道能不能,不过是个挺显然的转移方程
假设f[i][j]表示连续做了i道题,最大劳累值为j的方案数,是的,假期望,我们分两种情况,一个是最大值j是第i题贡献的,再一个就是最大值j是之前i-1道题中的某一道贡献的
所以,显然就是$f[i][j]=∑f[i-1][k]+f[i-1][j]*(j-1)$,如果是乘j-1前面k的范围就是$1<=k<=j$,如果乘j,前面k的范围就是$1<=k<=j-1$,就是保证那个选重复的情况不被包含两次且没人管就可以了,复杂度O(n3),鉴于n小,所以可做,如果n变大的话,可以选择用前缀和减少一维循环
1 #include<iostream> 2 #include<cstdio> 3 #define maxn 510 4 #define mod 1000000007 5 #define ll long long 6 using namespace std; 7 int n,m,k; 8 ll fz,fm,ans; 9 ll w[maxn]; 10 ll f[maxn][maxn]; 11 ll ksm(ll a,ll b,ll c) 12 { 13 ll ans=1; a=a%c; 14 while(b) 15 { 16 if(b&1) ans=(ans*a)%c; 17 b=b>>1; a=(a*a)%mod; 18 } 19 return ans; 20 } 21 int main() 22 { 23 scanf("%d%d%d",&n,&m,&k); 24 if(k>n) {printf("0\n"); return 0;} 25 for(int i=1;i<=m;++i) scanf("%lld",&w[i]); 26 for(int i=1;i<=m;++i) f[1][i]=1ll*1; 27 for(int i=2;i<=k;++i) 28 { 29 for(int j=1;j<=m;++j) 30 { 31 f[i][j]=(f[i][j]+(f[i-1][j]*j)%mod)%mod; 32 for(int k=1;k<=j-1;++k) f[i][j]=(f[i][j]+f[i-1][k])%mod; 33 } 34 } 35 fm=ksm(1ll*m,1ll*k,mod); 36 for(int i=1;i<=m;++i) fz=(fz+(f[k][i]*w[i])%mod)%mod; 37 fm=ksm(fm,mod-2,mod); 38 ans=(((fz*fm)%mod)*1ll*(n-k+1))%mod; 39 printf("%lld\n",ans); 40 return 0; 41 }