agc018 E - Sightseeing Plan
题目叙述
给定三个矩形,保证严格从左下到右上排列,每个矩形內部选择一个点,求从左下走到右上经过中间那个点的方案数。
题解
直接做是直接六个 的。不好。
考虑组合意义,相当于从左下矩形内的一个点出发,走到右上,计算中间这个矩形内路径中的点数之和。看起来这个转化其实没什么用,但实际上大有用处。
不能转化成这样之后,再拆分贡献转化回去。考虑将路径上的点数表示成 。
这怎么算,如果写成这样可能不容易看出来。。。应该写成 。
这样只需要枚举每个边界,计算经过这个边界的方案数量就可以了。
另外,别忘记 +1 ,这就是说统计经过这个矩形的路径数量。
总结
- 计数题要试着把答案代数化。
- 记得分类。合并一些答案。
代码
#include <cstdio>
#include <iostream>
#define y1 what_a_y1
#define macro_expand(x) #x
#define print_macro(x) printf("%s\n",macro_expand(x))
#define FOR(i,l,r) for(int i=(l),i##ADJK=(r);i<=i##ADJK;++i)
#define ROF(i,r,l) for(int i=(r),i##ADJK=(l);i>=i##ADJK;--i)
using namespace std;
typedef long long LL;
const int MN=1e6+6,RN=1e6,Mod=1e9+7;
int ad(int x,int y){return ((x+y)>=Mod)?(x+y-Mod):(x+y);}
int dc(int x,int y){return ((x-y)<0)?(x-y+Mod):(x-y);}
int ml(int x,int y){return (LL)x*y%Mod;}
int add(int &x,int y){return ((x+=y)>=Mod)?(x-=Mod):x;}
int dec(int &x,int y){return ((x-=y)<0)?(x+=Mod):x;}
int ksm(int x,int y){
int ret=1;
for(;y;y>>=1,x=ml(x,x))if(y&1)ret=ml(ret,x);
return ret;
}
int x1,x2,x3,x4,x5,x6;
int y1,y2,y3,y4,y5,y6;
int fac[MN*2],caf[MN*2];
void init(){
fac[0]=1;
FOR(i,1,2*RN)fac[i]=ml(fac[i-1],i);
caf[2*RN]=ksm(fac[2*RN],Mod-2);
ROF(i,2*RN-1,0)caf[i]=ml(caf[i+1],i+1);
}
int binom(int u,int d){
if(d<0||u<d)return 0;
return ml(fac[u],ml(caf[d],caf[u-d]));
}
int cal1(int A,int B,int C,int D){
return dc(ad(binom(B+D+2,D+1),binom(A+C,C)),ad(binom(A+D+1,D+1),binom(B+C+1,C)));
}
int cal2(int A,int B,int C,int D){
return ml(cal1(A-x2,A-x1,B-y2,B-y1),cal1(x5-C,x6-C,y5-D,y6-D));
}
int ans;
int main(){
freopen("e.in","r",stdin);
freopen("e.out","w",stdout);
init();
scanf("%d%d%d%d%d%d",&x1,&x2,&x3,&x4,&x5,&x6);
scanf("%d%d%d%d%d%d",&y1,&y2,&y3,&y4,&y5,&y6);
int cnt=0;
FOR(i,x3,x4){
int tmp=0;
add(cnt,tmp=cal2(i,y4,i,y4+1));
add(ans,ml(i+y4,tmp));
}
FOR(i,y3,y4){
int tmp=0;
add(cnt,tmp=cal2(x4,i,x4+1,i));
add(ans,ml(x4+i,tmp));
}
add(ans,cnt);
FOR(i,y3,y4)dec(ans,ml(x3+i,cal2(x3-1,i,x3,i)));
FOR(i,x3,x4)dec(ans,ml(i+y3,cal2(i,y3-1,i,y3)));
printf("%d\n",ans);
fclose(stdin);
fclose(stdout);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通