Highways UVA - 1393

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<ctime>
#define bug(x) printf("***%d\n",x)
using namespace std;

typedef long long ll;

/*
这道题和(Trees int a wood) 特别像,因为都是找一个gcd(x,y)==1的点 的个数,只不过那道题只有一个固定点,
然后所有的位置都是相对于原点来说的,这道题的 “固定点" 不只有一个,最麻烦的是还会有重复,所以最难的点,就是 去重
1.(统计小矩形的长和宽)   想的就是 只保留 最后一行和最后一列,这样的话,肯定不会有重复的,但是漏了 一些情况 比如:
                          * * *
                          * * * , 如果要 宽为2,高为1的话,应该有四个这样的 直线,但是要是按照上面的统计方法,就会遗漏左上角的那个,因为没有和他重复的
                          所以紫书上写的方法是, 看整个 矩形能放多少个,然后减去(在右下角有小矩形的前提下)左上角能放的小矩形的数量,这样就会 全部统计出来了
2.dp
*/

ll Gcd[310][310];
ll gcd(ll a,ll b){
    return b==0?a:gcd(b,a%b);
}

void init(){
    for(ll i=1;i<=300;i++){
        for(ll j=i;j<=300;j++){
            Gcd[i][j]=Gcd[j][i]=gcd(i,j);
        }
    }
}

int main(){

    init();
    ll n,m;
   // freopen("123.txt","r",stdin);
   // freopen("456.txt","w",stdout);
    while(scanf("%lld %lld",&n,&m)==2&&n){
       // printf("n:%d m:%d\n",n,m);
        ll ans=0;
        for(ll i=1;i<n;i++){
            for(ll j=1;j<m;j++){
                if(Gcd[i][j]==1){
                   ans+=(n-i)*(m-j);
                   ll t1=max((ll)0,n-2*i),t2=max((ll)0,m-2*j);;
                   ans-=t1*t2;
                }
            }
        }
        printf("%lld\n",ans*2);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36424540/article/details/81106868
今日推荐