画直线
Description
鹏鹏最近迷恋上了画直线。平面上有N^2个点(N行每行N个),任取两点可以画一条直线,鹏鹏左手画一根,右手画一根乐此不疲的玩着。
过了好久,鹏鹏感觉这样无聊了。于是,他想知道他一共可以画多少条不平行的直线。
Input
第一行一个整数T(T<=1000),测试的组数。
接下来T行每行一个整数N(1<N<=1000),表示鹏鹏画线的范围。
Output
每行对应输出鹏鹏所能画线的总数
Sample Input
2
2
3
Sample Output
4
8
Source
ACM/ICPC Team of Zhengzhou University
超级水的题啊,强哥出的题,坑了无数人
这个题其实只用判断最大公约数就可以了
因为点是关于对角线对称的,因此我只分析了点阵的左下角
n == 2时
(0,0)
(1,0) (1,1)
取:(0,0) --- (1,0)
(0,0) --- (1,1)
这里有两条,与其垂直的也有两条,共四条
-------------------------------
n == 3时
取:
(0,0)
(1,0) (1,1)
(2,0) (2,1) (2,2)
可以取的直线有:(只需考虑第3行)
因为考虑第二行与第三的连线时等价于重复1 2行
因此只考虑第3行到(0, 0)
而(2,0) (2,2)也不需考虑,因为重复了
故只考虑(2,1),2和1的最大公约数是1,所以可以判定之前没出现过,所以这个点与(0,0)可以连线
再以对称来看(1,0) (2,2)也可以连线,所以结果要乘以4
n == 4时同上分析。。。
现在知道这道题有多水了吧
另外这里的鹏鹏就是卢凯鹏学长
代码如下:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#define MAXN 10010
#define ll long long
using namespace std;
int b[MAXN];
bool gcd(int x, int y){
int temp;
if(x > y){
temp = x;
x = y;
y = temp;
}
while(x != 0){
temp = x;
x = y%x;
y = temp;
}
// cout << y << endl;
if(y == 1)
return true;
return false;
}
int main(void) {
int T, n;
scanf("%d", &T);
b[2] = 4;
for(int i=3; i<=1010; ++i) {
b[i] = b[i-1];
int count = 0;
for(int j=1; j<i; ++j){
if(gcd(i-1, j))
count++;
}
b[i] += 4*count;
/*
cout << "i = " << i << endl;
cout << "count = " << count << endl;
cout << "b[" << i << "] = " << b[i] << endl;
system("pause");
*/
}
while(T--) {
scanf("%d", &n);
printf("%d\n", b[n]);
}
return 0;
}