自闭了,题解都看不懂。
Desprition
小 Y 十分喜爱光学相关的问题, 一天他正在研究折射. 他在平面上放置了 (n) 个折射装置, 希望利用这些装置画出美丽的折线
折线将从某个装置出发, 并且在经过一处装置时可以转向, 若经过的装置坐标依次为 ((x1, y1),(x2, y2)) . . .((xk, yk)),
则必须满足:
• (∀) $j in (1, k], y_{j-1} < y_j $
• (∀) (j in (2 ,k]), (x_{j- 2} < x_j < x_{j_1}) (or) $ x_{j-1} < x_j < x_{j-2}$
现在他希望你能告诉他, 一共有多少种不同的光线能被他画出来, 两种光线不同当且仅当经过的折射装置的集合不同
. 你只需要告诉他答案对 (10^9 +7) 取模后的结果
.Input Format
第一行一个正整数 (n) , 表示折射装置的数量 接下来 (n) 行, 每行两个整数 (x_i , y_i) 表示折射装置的坐标
Output Format
输出一行一个整数, 表示答案对 (10^9 +7) 取模后的结果
.Constraints
对于 10% 的数据: (n≤ 700, 1 ≤ x_i, y_i≤N)
对于 20% 的数据: (n≤ 1000, 1 ≤x_i, y_i≤N)
对于 50% 的数据: (n≤ 4000,|x_i|,|y_i | ≤ 10^9)
对于 100% 的数据: (n ≤ 6000,|x_i|,|y_i| ≤ 10^9)
sloution
自闭了,考试的时候连 (O(n^2)) 的暴力都不会,直接粘题解吧
设 (dp[i][0/1]) 表示按 (x) 排序,以 (i) 为入射点的光线,向左下方 0/右下方1入射,注意这里前 (i) 并不是状态,因为
后面可以更改这个 (dp_i) 状态。按 (x) 排序只是方便处理。
转移:
(∀) (y_j < y_i, dp[i][0] <- dp[j][1])
(∀) (y_j > y_i) ,(dp[j][1] <- dp[k][0]) (y_k < y_j and x_k > x_j)
搬运完成
不知道为什么把 (f[i][0],f[i][1]) 初始化放在外面就不对。
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 6010;
const int p = 1e9+7;
int n,ans,f[N][2];
struct node
{
int x,y;
}e[N];
inline int read()
{
int s = 0,w = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
return s * w;
}
bool cmp(node a,node b)
{
return a.x < b.x;
}
int main()
{
freopen("refract.in","r",stdin);
freopen("refract.out","w",stdout);
n = read();
for(int i = 1; i <= n; i++)
{
e[i].x = read();
e[i].y = read();
}
sort(e+1,e+n+1,cmp);
f[1][0] = f[1][1] = 1;
for(int i = 2; i <= n; i++)
{
f[i][0] = f[i][1] = 1;
for(int j = i-1; j; j--)
{
if(e[j].y > e[i].y) f[j][1] += f[i][0], f[j][1] %= p;
if(e[j].y < e[i].y) f[i][0] += f[j][1], f[i][0] %= p;
}
}
for(int i = 1; i <= n; i++) ans = (1LL * ans + f[i][0] + f[i][1]) % p;
printf("%d
",(ans - n + p) % p);
fclose(stdin); fclose(stdout);
return 0;
}