解法
首先要分析出什么时候能组成正方形,设三点为(x0,y0)
,(x1,y1)
,(x2,y2)
- 三点一线时,一定可行
- 三点不一线时,一定可以把这三个点按x排序,使得
x0<=x1<=x2
且x0<x2
。这时,(x0,y0)
,(x2,y2)
可组成矩形。
分析可知,当(x1,y1)
在这个矩形里面(不包括边)时,就无法通过正方形访问
所以算法很简单了,求出不合法的种数,再用 C n 3 C_n^3 Cn3减去它。
解法:小数据集
对于小数据集,第一反应是枚举x
不同的点对,然后判断它们之间有多少不合法点
解法:大数据集
不能枚举点对了,遍历每个点(x,y)
,看它在哪些点对里:
- (# of 横坐标小于x,纵坐标大于y)*(# of 横坐标大于x,纵坐标小于y)
- (# of 横坐标小于x,纵坐标小于y)*(# of 横坐标大于x,纵坐标大于y)
就这两类点对
一个重要的坑!!!!!!!!
容易预测到大数据集的ans
得用long long
,但是还要注意的是,由于坐标和点数最大都有
1
0
5
10^5
105和
1
0
6
10^6
106,所以它们相乘的时候还是有可能溢出,这些地方也要用long long
#include <stdio.h>
#include <unordered_map>
#include <string>
#include <iostream>
#include <memory.h>
#include <stdlib.h>
#include <set>
#include <map>
#include <cmath>
using namespace std;
class BIT {
int *c;
int capa;
public:
BIT(int size) {
c = new int [size];
memset(c,0,sizeof(int)*size);
capa = size;
}
static int lowbit(int k){
return k&(0-k);
}
void add(int k) {
k += 1;
while(k<=capa) {
c[k-1]++;
k += lowbit(k);
}
}
void del(int k) {
k += 1;
while(k<=capa) {
c[k-1]--;
k += lowbit(k);
}
}
int sum(int k) {
int res = 0;
k += 1;
while(k>=1) {
res += c[k-1];
k -= lowbit(k);
}
return res;
}
~BIT() {
delete [] c;
}
};
void insert(map<int,set<int>> &maps, int v, int h) {
if (maps.find(v)==maps.end())
maps[v] = set<int>();
maps[v].insert(h);
}
long long solve(map<int,set<int>> &maps, int m, BIT &total,int n) {
long long res = 0;
BIT lower(m);
int l = 0, h = n;
for(auto i = maps.begin();i!=maps.end();++i) {
for(auto &y:i->second) {
total.del(y);
}
h -= i->second.size();
for(auto &y:i->second) {
long long llo,lhi,rlo,rhi;
llo = y>0?lower.sum(y-1):0;
lhi = l-lower.sum(y);
rlo = y>0?total.sum(y-1):0;
rhi = h-total.sum(y);
res += llo*rhi+lhi*rlo;
}
for(auto &y:i->second) {
lower.add(y);
}
l += i->second.size();
}
return res;
}
int main() {
int t;
scanf("%d",&t);
for(auto round=1;round<=t;++round) {
map<int,set<int>> maps;
int n,v,h,m;
long long a,b,c,d,e,f;
scanf("%d%d%d%lld%lld%lld%lld%lld%lld%d",&n,&v,&h,&a,&b,&c,&d,&e,&f,&m);
BIT total(m);
insert(maps,v,h);
total.add(h);
for(int i=2;i<=n;++i) {
long long x = (a*v+b*h+c)%m,y = (d*v+e*h+f)%m;
v = x; h = y;
// printf("(%d,%d)\n",x,y);
maps[v].insert(h);
total.add(h);
}
// int n;
// scanf("%d",&n);
// for(int i=0;i<n;++i) {
// int v,h;
// scanf("%d%d",&v,&h);
// insert(maps,v,h);
// }
// int m = 1000;
long long ans = n;
ans *= n-1;
ans *= n-2;
printf("Case #%d: %lld\n",round, ans/6-solve(maps,m,total,n));
}
}