hdu 5116--Everlasting L(计数DP)

题目链接

Problem Description

Matt loves letter L.

A point set P is (a, b)-L if and only if there exists x, y satisfying:

P = {(x, y), (x + 1, y), . . . , (x + a, y), (x, y + 1), . . . , (x, y + b)}(a, b ≥ 1)

A point set Q is good if and only if Q is an (a, b)-L set and gcd(a, b) = 1.

Matt is given a point set S. Please help him find the number of ordered pairs of sets (A, B) such that:

Input

The first line contains only one integer T , which indicates the number of test cases.

For each test case, the first line contains an integer N (0 ≤ N ≤ 40000), indicating the size of the point set S.

Each of the following N lines contains two integers xi, yi, indicating the i-th point in S (1 ≤ xi, yi ≤ 200). It’s guaranteed that all (xi, yi) would be distinct.

Output

For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1) and y is the number of pairs.

Sample Input

2

6

1 1

1 2

2 1

3 3

3 4

4 3

9

1 1

1 2

1 3

2 1

2 2

2 3

3 1

3 2

3 3

Sample Output

Case #1: 2

Case #2: 6

Hint

n the second sample, the ordered pairs of sets Matt can choose are:

A = {(1, 1), (1, 2), (1, 3), (2, 1)} and B = {(2, 2), (2, 3), (3, 2)}

A = {(2, 2), (2, 3), (3, 2)} and B = {(1, 1), (1, 2), (1, 3), (2, 1)}

A = {(1, 1), (1, 2), (2, 1), (3, 1)} and B = {(2, 2), (2, 3), (3, 2)}

A = {(2, 2), (2, 3), (3, 2)} and B = {(1, 1), (1, 2), (2, 1), (3, 1)}

A = {(1, 1), (1, 2), (2, 1)} and B = {(2, 2), (2, 3), (3, 2)}

A = {(2, 2), (2, 3), (3, 2)} and B = {(1, 1), (1, 2), (2, 1)}

Hence, the answer is 6.

题意:对于点集P 如果存在a,b使得P = {(x, y), (x + 1, y), . . . , (x + a, y), (x, y + 1), . . . , (x, y + b)}(a, b ≥ 1),并且a,b互质,则P is good 。可以发现对于符合要求(good)的集合P ,其构成一个L 型,且以(x,y)为拐点,从(x,y)向上长度和向右长度互质。现在给了N个点,求有多少对符合要求的L型集合不相交(集合交集为空)?

思路:先找到所有符合要求的L个数S,那么用S*S-相交的L对数  即为结果。

怎么算相交的所有L对数呢? 容斥,很妙的思想,遍历每一个点,如果当前的点是输入的点之一,那么是一个拐点,令这个拐点向右延伸最长为k,那么算出所有其它L的竖着部分与(x,y+k)相交的对数,乘以2,另外要考虑以(x,y)为拐点的L与自身相交的情况,把这两种相交情形减掉后既是结果。

代码如下:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int N=40050;
const int M=205;
int R[M][M],U[M][M];
bool mp[M][M];
int dp[M][M],cnt[M][M];
int t[M][M];

int gcd(int a,int b) { return (b==0)?a:gcd(b,a%b); }

void init()
{
    for(int i=1;i<M;i++)
    for(int j=1;j<M;j++)
    {
        dp[i][j]=dp[i][j-1]+((gcd(i,j)==1)?1:0);
        cnt[i][j]=cnt[i-1][j]+dp[i][j];
    }
}
int main()
{
    init();
    int T,Case=1;
    cin>>T;
    while(T--)
    {
        int n;  scanf("%d",&n);
        memset(mp,0,sizeof(mp));
        memset(U,0,sizeof(U));
        memset(R,0,sizeof(R));
        memset(t,0,sizeof(t));
        for(int i=1;i<=n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            mp[x][y]=1;
        }
        for(int i=200;i>=1;i--)
        {
            for(int j=200;j>=1;j--)
            {
                if(mp[i][j]){
                   if(mp[i+1][j]) U[i][j]=U[i+1][j]+1;
                   if(mp[i][j+1]) R[i][j]=R[i][j+1]+1;
                }
            }
        }
        LL s=0;
        for(int i=1;i<=200;i++)
        {
            for(int j=1;j<=200;j++)
            {
                if(mp[i][j]){
                    s+=cnt[U[i][j]][R[i][j]];
                    int d=0;
                    for(int k=U[i][j];k>=0;k--)
                    {
                        d+=dp[k][R[i][j]];
                        t[i+k][j]+=d;
                    }
                }
            }
        }
        LL ans=0;
        for(int i=1;i<=200;i++)
        {
            for(int j=1;j<=200;j++)
            {
                if(mp[i][j]){
                    LL p=t[i][j];
                    LL pp=cnt[U[i][j]][R[i][j]];
                    p-=pp;
                    for(int k=1;k<=R[i][j];k++)
                    {
                        p+=t[i][j+k];
                        ans+=2*p*dp[k][U[i][j]];
                    }
                    ans+=pp*pp;
                }
            }
        }
        s=s*s-ans;
        printf("Case #%d: %lld\n",Case++,s);
    }
    return 0;
}
时间: 2024-11-07 02:08:48

hdu 5116--Everlasting L(计数DP)的相关文章

动态规划(DP计数):HDU 5116 Everlasting L

Matt loves letter L. A point set P is (a, b)-L if and only if there exists x, y satisfying: P = {(x, y), (x + 1, y), . . . , (x + a, y), (x, y + 1), . . . , (x, y + b)}(a, b ≥ 1) A point set Q is good if and only if Q is an (a, b)-L set and gcd(a, b)

HDU 5116 Everlasting L

题意:给定若干个整数点,若一个点集满足P = {(x, y), (x + 1, y), . . . , (x + a, y), (x, y + 1), . . . , (x, y + b)}(a, b ≥ 1)  且 gcd(a, b)==1 则称这是一个好(a, b)-L集.求共有多少个(A, B)满足A,B都是好L集且A,B不相交. 思路是先找出好L集的数量a,再找出相交的好L集对数b,则答案为a * a - b . 首先要解决的第一个问题是求出a,一个自然的思路是对于每个点,分别向右.向下

HDU 4055 Number String 计数DP

设dp[i][j]表示以j开头的,长度为i的排列的数目. 从字符串的后面到前面DP就得出答案了. #include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> using namespace std; const int MAXN=1010; const int MOD=1000000007; char str[MAXN]; int dp[MAXN][MAXN]; in

HDU 1978 How many ways (DP,计数)

http://acm.hdu.edu.cn/showproblem.php?pid=1978 How many ways Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3022    Accepted Submission(s): 1771 Problem Description 这是一个简单的生存游戏,你控制一个机器人从一个棋盘的起

hdu 4901 The Romantic Hero(计数dp)2014多校训练第4场1005

The Romantic Hero                                                                               Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description There is an old country and the king fell in lov

hdu 5136 Yue Fei&#39;s Battle(计数DP)

Yue Fei's Battle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others) Total Submission(s): 151    Accepted Submission(s): 48 Problem Description Yue Fei is one of the most famous military general in Chinese history.He

HDU 4832 组合计数dp

Chess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 509    Accepted Submission(s): 198 Problem Description 小度和小良最近又迷上了下棋.棋盘一共有N行M列,我们可以把左上角的格子定为(1,1),右下角的格子定为(N,M).在他们的规则中,"王"在棋盘上的走法遵循十字

HDU 6377 度度熊看球赛 (计数DP)

度度熊看球赛 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 293    Accepted Submission(s): 130 Problem Description 世界杯正如火如荼地开展!度度熊来到了一家酒吧. 有 N 对情侣相约一起看世界杯,荧幕前正好有 2×N 个横排的位置. 所有人都会随机坐在某个位置上. 当然,如果某一对情

HDU4815/计数DP

题目链接[http://acm.hdu.edu.cn/showproblem.php?pid=4815] 简单说一下题意: 有n道题,每到题答对得分为a[ i ],假如A不输给B的最小概率是P,那么A最少要得到多少分. 解题过程: 假设有n道题,每个题有两个状态,胜或者败,假设达到某个分数m有k(计数DP)种方式,那么最后是这个分数的概率是k/pow(2,n).那么A不输给B的概率就是小于等于m的分数的概率和. #include<bits/stdc++.h> const int maxn =