Zoj 3647 Gao the Grid (数论?)

来源:互联网 发布:国家电网大厅数据运维 编辑:程序博客网 时间:2024/05/02 00:03

给你n * m 的的矩形方格, 也即有(n + 1) * (m + 1) 个点, 然后问可以找到做少个三角形。

n比较大显然是不能暴力枚举的, 然后想dp递推也发现太复杂了,,于是想逆向求解,比赛的时候想的是枚举斜率, 然后判断当前斜率下右多少点共线, 再考虑平移, 可是还是不对,,跟ac代码比了很多样例都是没问题的。。醉了。

然后Ac代码的解题方式是, 枚举每条直线的一个端点, 另一个端点是0,0,然后这条直线上,选两个端点的情况下, 不符合条件的方法数就是__gcd(i, j) - 1。然后再考虑平移然后再乘二,再用总的方法数减掉就可以了。

#include <set>#include <map>#include <queue>#include <stack>#include <cmath>#include <string>#include <cctype>#include <cstdio>#include <vector>#include <cstdlib>#include <cstring>#include <iomanip>#include <sstream>#include <iostream>#include <algorithm>using namespace std;#define ls id<<1,l,mid#define rs id<<1|1,mid+1,r#define OFF(x) memset(x,-1,sizeof x)#define CLR(x) memset(x,0,sizeof x)#define MEM(x) memset(x,0x3f,sizeof x)typedef long long ull ;typedef pair<int,int> pii ;const int maxn = 1e5+50 ;const int inf = 0x3f3f3f3f ;const int MOD = 1e9+7 ;ull a[1055];void init() {    a[2] = 0;    for (int i = 3; i <= 1005; i++) a[i] = a[i - 1] + i * (i - 1) * (i - 2) / 6;//    cout << a[1000] << "\n" ;}int main () {#ifdef LOCALfreopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);//      freopen("C:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);#endif    int n,m;init();    while (~scanf("%d%d", &n, &m)) {        ull tmp = 0;        for (int i = 2; i <= n; i++) {            for (int j = 2; j <= m; j++) {                tmp += 1LL * (__gcd(i,j) - 1) * (n - i + 1) * (m - j + 1) * 2;            }        }        tmp += 1LL * (m + 1) * (n + 1) * (n - 1) * n / 6;        tmp += 1LL * (n + 1) * (m + 1) * (m - 1) * m / 6;        ull d = (m + 1) * (n + 1);        ull ans = d * (d - 1) * (d - 2) / 6;        cout << ans - tmp << "\n" ;    }return 0;}


0 0