Uva(1393)(Highways)

链接:https://vjudge.net/problem/UVA-1393
思路:代码很短,但是却不好想,首先我们要考虑如果确定两点怎么判断他们能否形成一条之前没有重复过的直线,方法就是看他的向量的gcd是否为1,不为1则前面肯定计算过,所以我们考虑预处理的时候用dp[i][j]表示向量(x,y)(x<y,y<j)一共有多少个是互质的,则递推式为 dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + (gcd(i,j)==1),接下来我们处理所有点,当到点(i,j)时,内部各点与他组成的向量范围都在[1,i-1][1,j-1]内,那么可以用dp[i-1][j-1]表示其中有多少与其互质,但是会有重复计算的,我们思考一下重复计算的是哪些,必定是向量间满足二倍关系的(上面一半计算了一次,下面一半又计算了一次),所以再减去dp[(i-1)/2][(j-1)/2]即可,为了方便书写我们把所有i,j都+1,最后答案的时候找对应n-1的值即可
代码

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

int n,m;
long long dp[305][305];
long long ans[305][305];

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

int main(){
    for(int i=1;i<=300;i++){
        for(int j=1;j<=300;j++){
            dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + (gcd(i,j)==1);
        }
    }
    for(int i=1;i<=300;i++){
        for(int j=1;j<=300;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];
        }
    }
    while(scanf("%d%d",&n,&m)&&(n||m)){
        printf("%lld\n",ans[n-1][m-1]*2);
    }
    return 0;
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 14,352评论 0 33
  • 各校历年复试机试试题 清华、北大、华科试题详细笔记部分,少笔记部分与少数leetcode【含个人整理笔记】 一、详...
    医学工程与科学园地阅读 4,969评论 0 1
  • 动态规划(Dynamic Programming) 本文包括: 动态规划定义 状态转移方程 动态规划算法步骤 最长...
    廖少少阅读 8,771评论 0 18
  • thiele插值算法 1点插值算法 function [C,c]=thiele(X,Y,Z)%X为插值点横坐标,Y...
    00crazy00阅读 6,251评论 0 4
  • 猫昨天给我看一个关于水瓶的故事,故事大意是“要把最好的自己留给最好的那个人”,我知道猫看得很难过,其实我也很难过。...
    cuckoo酱阅读 1,202评论 0 0