UVA 1393 - Highways(数论+DP)

题目链接 https://cn.vjudge.net/problem/UVA-1393

【题意】
有一个n行m列的点阵(1<=n,m<=300)一共有多少条非水平非竖直的线穿过其中的两个点?

【思路】
递推,设 ans[i][j]ij 个方块对应的答案,那么

ans[i][j]=ans[i][j1]+ans[i1][j]+ans[i1][j1]+x
最后的这个x是最下面最右面的那个点所做贡献,那么这个 x 应该是多少呢,应该是 x[1,i]  y[1,j]gcd(x,y)=1 的整数对的个数减去之前已经被计算过的整数对个数,之前就被计算过的整数对一定是规模缩小1倍后仍然存在的整数对个数

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn=330;

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

ll dp[maxn][maxn];
ll ans[maxn][maxn];

int main(){
    for(int i=1;i<maxn;++i){
        for(int j=1;j<maxn;++j){
            dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+(gcd(i,j)==1?1:0);
        }
    }
    for(int i=1;i<maxn;++i){
        for(int j=1;j<maxn;++j){
            ans[i][j]=ans[i-1][j]+ans[i][j-1]-ans[i-1][j-1]+dp[i][j]-dp[i/2][j/2];
        }
    }
    int n,m;
    while(scanf("%d%d",&n,&m)==2){
        if(0==n && 0==m) break;
        printf("%lld\n",ans[n-1][m-1]*2);
    }
    return 0;
}
posted @ 2018-08-29 23:01  不想吃WA的咸鱼  阅读(194)  评论(0)    收藏  举报