CodeForces - 1549F1 Gregor and the Odd Cows (Easy)(几何+数论)
Posted Frozen_Guardian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces - 1549F1 Gregor and the Odd Cows (Easy)(几何+数论)相关的知识,希望对你有一定的参考价值。
题目链接:点击查看
题目大意:给出二维平面上的 n n n 个点,任意选择出三个点可以构成一个三角形,现在问满足下面条件的三角形的个数:
- 三角形面积为整数
- 三角形包含的(不包括边界)整数点为奇数
其中所有坐标点的 x x x 和 y y y 都是偶数
题目分析:因为所有坐标点都是偶数,所以先猜一波任意三个点都是满足第一个条件的,也就是围成的三角形面积一定是偶数。
所以现在问题就转换为了,如何求解满足第二个条件的三角形的个数。赛中经队友提醒,得知了“皮克定理”这一关键的结论,即 S = a + b 2 − 1 S=a+\\frac{b}{2}-1 S=a+2b−1,其中 S S S 为三角形的面积, a a a 为三角形内部的点数, b b b 为三角形边界上的点数。 b b b 非常好求,每条边上的答案就是 gcd ( d x , d y ) + 1 \\gcd(dx,dy)+1 gcd(dx,dy)+1,放在三角形上就是 gcd ( ∣ x 1 − x 2 ∣ , ∣ y 1 − y 2 ∣ ) + gcd ( ∣ x 1 − x 3 ∣ , ∣ y 1 − y 3 ∣ ) + gcd ( ∣ x 3 − x 2 ∣ , ∣ y 3 − y 2 ∣ ) + 3 − 3 \\gcd(|x1-x2|,|y1-y2|)+\\gcd(|x1-x3|,|y1-y3|)+\\gcd(|x3-x2|,|y3-y2|)+3-3 gcd(∣x1−x2∣,∣y1−y2∣)+gcd(∣x1−x3∣,∣y1−y3∣)+gcd(∣x3−x2∣,∣y3−y2∣)+3−3,因为三个顶点分别计算了两次,所以减去三之后就是这个答案了
皮克定理移项之后得到 a = b 2 − 1 − S a=\\frac{b}{2}-1-S a=2b−1−S,如果 a a a 想要为奇数,那么 a + 1 = b 2 − S a+1=\\frac{b}{2}-S a+1=2b−S 需要是偶数,因为上面已经保证了 S S S 是偶数,所以现在只需要保证 b 2 \\frac{b}{2} 2b 是偶数
所以问题转换为了,有 n n n 个点,任意两个点之间的边权为 g c d ( d x , d y ) / 2 gcd(dx,dy)/2 gcd(dx,dy)/2,现在要求满足条件的三元环个数,需要满足三条边权为:
- 奇数、奇数、偶数
- 偶数、偶数、偶数
然后到这里就尬住了,比赛时以为是什么典中典的三元环计数问题,就下班了
第二天看了题解发现,边权和坐标有着密切的联系,又因为每个点的坐标都是偶数,所以我们不妨一开始就将坐标除以二
然后我们就很神奇的发现,一共就只有四类点了,分别是 x x x 和 y y y 分别取 0 0 0 或 1 1 1 的时候。这是点权,边权的话当且仅当 x 1 = = x 2 x1==x2 x1==x2 and y 1 = = y 2 y1==y2 y1==y2 时,原先点的 gcd \\gcd gcd 才是偶数,其他情况都是奇数
从头开始再推一遍,发现我们之前的得到的结论没有变!所以 n 3 n^3 n3 去枚举计数就好了
你说 n = 6000 n=6000 n=6000?不不,现在的 n n n 实质上只有 4 4 4 种情况,用组合数学统计一下答案就好了
代码:
// Problem: F1. Gregor and the Odd Cows (Easy)
// Contest: Codeforces - Codeforces Round #736 (Div. 2)
// URL: https://codeforces.com/contest/1549/problem/F1
// Memory Limit: 256 MB
// Time Limit: 6000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<list>
#include<unordered_map>
#define lowbit(x) (x&-x)
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
T f=1;x=0;
char ch=getchar();
while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
x*=f;
}
template<typename T>
inline void write(T x)
{
if(x<0){x=~(x-1);putchar('-');}
if(x>9)write(x/10);
putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=1e6+100;
LL cnt[2][2];
LL C(int n,int m) {
if(m==1) {
return n;
} else if(m==2) {
return 1LL*n*(n-1)/2;
} else if(m==3) {
return 1LL*n*(n-1)*(n-2)/6;
}
}
int cal(int x1,int y1,int x2,int y2) {
if(x1==x2&&y1==y2) {
return true;
} else {
return false;
}
}
int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);
int n;
read(n);
for(int i=1;i<=n;i++) {
int x,y;
read(x),read(y);
cnt[x%4/2][y%4/2]++;
}
LL ans=0;
for(int s1=0;s1<4;s1++) {
for(int s2=s1;s2<4;s2++) {
for(int s3=s2;s3<4;s3++) {
int x1=s1/2,y1=s1%2;
int x2=s2/2,y2=s2%2;
int x3=s3/2,y3=s3%2;
int even=0;
//2odds + 1even or 3 even
even+=cal(x1,y1,x2,y2);
even+=cal(x1,y1,x3,y3);
even+=cal(x2,y2,x3,y3);
if(even==2||even==0) {
continue;
}
if(s1==s2&&s2==s3) {
ans+=C(cnt[x1][y1],3);
} else if(s1==s2) {
ans+=C(cnt[x1][y1],2)*cnt[x3][y3];
} else if(s2==s3) {
ans+=C(cnt[x2][y2],2)*cnt[x1][y1];
} else if(s1==s3) {
ans+=C(cnt[x1][y1],2)*cnt[x2][y2];
} else {
ans+=cnt[x1][y1]*cnt[x2][y2]*cnt[x3][y3];
}
}
}
}
cout<<ans<<endl;
return 0;
}
以上是关于CodeForces - 1549F1 Gregor and the Odd Cows (Easy)(几何+数论)的主要内容,如果未能解决你的问题,请参考以下文章