打卡信奥刷题(2997)用C++实现信奥题 P6149 [USACO20FEB] Triangles S
本文介绍了USACO 2020年2月比赛中的一道题目"Triangles S"。题目要求计算在给定N个二维平面点中,所有满足特定条件的三角形面积之和的两倍模1e9+7的值。具体条件是三角形必须有一条边与x轴平行,另一条边与y轴平行。文章提供了样例解释和C++实现代码,该代码通过排序和预处理优化计算过程。作者表示后续将继续分享算法竞赛相关的内容,包括GESP考级和各类编程比赛题目
P6149 [USACO20FEB] Triangles S
题目描述
Farmer John 想要给他的奶牛们建造一个三角形牧场。
有 NNN(3≤N≤1053\leq N\leq 10^53≤N≤105)个栅栏柱子分别位于农场的二维平面上不同的点 (X1,Y1)…(XN,YN)(X_1,Y_1)\ldots (X_N,Y_N)(X1,Y1)…(XN,YN)。他可以选择其中三个点组成三角形牧场,只要三角形有一条边与 xxx 轴平行或重合,且有另一条边与 yyy 轴平行或重合。
FJ 可以组成的所有可能的牧场的面积之和等于多少?
输入格式
第一行包含 NNN。
以下 NNN 行每行包含两个整数 XiX_iXi 和 YiY_iYi,均在范围 −104…104−10^4\ldots 10^4−104…104 之内,描述一个栅栏柱子的位置。
输出格式
由于面积之和不一定为整数且可能非常大,输出面积之和的两倍模 109+710^9+7109+7 的余数。
输入输出样例 #1
输入 #1
4
0 0
0 1
1 0
1 2
输出 #1
3
说明/提示
样例解释:
栅栏木桩 (0,00,00,0)、(1,01,01,0) 和 (1,21,21,2) 组成了一个面积为 111 的三角形,(0,00,00,0)、(1,01,01,0) 和 (0,10,10,1) 组成了一个面积为 0.50.50.5 的三角形。所以答案为 2×(1+0.5)=32\times (1+0.5)=32×(1+0.5)=3。
子任务:
- 测试点 222 满足 N=200N=200N=200。
- 测试点 333-444 满足 N≤5000N\leq 5000N≤5000。
- 测试点 555-101010 没有额外限制。
C++实现
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 100005
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
int n;
struct node{
int x,y;
bool operator<(const node o)const{
if(x^o.x)return x<o.x;
return y<o.y;
}
}a[N];
typedef long long ll;
ll ans=0;const ll P = 1000000007LL;const int bas = 10007;
ll sum[N],cnt[N];
void solve(){
sort(a+1,a+n+1);
memset(sum,0,sizeof(sum));
memset(cnt,0,sizeof(cnt));
ll now = 0,tot = 0 ;
rep( i , 1 , n ){
if(a[i].x != a[i-1].x )now = 0 ,tot = 0 ;
ans=(ans + ( a[i].x * cnt[a[i].y + bas] - sum[ a[i].y + bas ] )
% P * ( a[i].y * tot - now ) % P ) % P;
tot++;now=(now+a[i].y)%P;
cnt[a[i].y+bas]++;
sum[a[i].y+bas]=(a[i].x+sum[a[i].y+bas])%P;
}
}
void rev(){
rep(i,1,n){
int x=a[i].x,y=a[i].y;
a[i].x=y;a[i].y=-x;
}
}
int main(){
scanf("%d",&n);
rep(i,1,n)scanf("%d%d",&a[i].x,&a[i].y);
rep(i,0,3){
solve();rev();
}
printf("%lld\n",ans);
return 0;
}

后续
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容
更多推荐



所有评论(0)