zoukankan      html  css  js  c++  java
  • UVALive 3720 UVA 1393 Highways

    这是白书二代上的一个组合计数里面的一道练习题。

    我用的方法是枚举在x*y的方格中放置一条对角线,也可以理解为枚举斜率。

    如图,先来看这样一个问题,n=m=4,即此时有3行3列的方格的时候,可以放置斜率k=-1的直线有多少条。

    首先我们把每个格子都标上号。如图,我最多只能放置5条k=-1的直线。

    当我枚举在1*1的方格中放置对角线的时候(当然此时斜率k=-1),一共可以放置9条对角线。

    然而事实上斜率k=-1的对角线只需要5条就可以了,多出来了4条。那么是哪里多出来了这4条呢?

    我们注意看所有2*2的方格,他们多有的右下角的那条都是多余的。如图:

    很显然,我们需要删掉1245中的5,2356中的6,4578中的8,5689中的9,此时留下来的123475条直线可以代表所有斜率为-1的直线。

    同理,当n!=m的时候,结果也是一样的。

    再来考虑斜率不是-1的情况(当然我这里只是举了斜率为负的例子,斜率为正的情况和斜率为负的情况必定都是一样的,最后在结果*2就可以了。)

    其实道理还是一样的,如果gcd(x,y)=1,可以保证这样的斜率是第一次出现,则我们只需要把每x*y格看成是1格就行了。

    如果gcd(x,y)=2,这样的斜率是第二次出现了,这就类似于上面所说的2*2的情况了,对于所有这样的矩形,他的右下角部分都是多余的。

    贴一下我的代码:

    View Code
     1 #include<cstdio>
     2 int gcd[310][310];
     3 int Gcd(int a,int b)
     4 {
     5     return b == 0 ? a : Gcd(b,a%b);
     6 }
     7 int main()
     8 {
     9     for(int i = 1;i <= 300;i++)
    10         for(int j = i;j <= 300;j++)
    11             gcd[i][j] = Gcd(i,j);
    12     int n,m;
    13     long long int ans;
    14     while(scanf("%d%d",&n,&m) == 2)
    15     {
    16         if(!n && !m)    break;
    17         n--;m--;
    18         if(n > m)   n ^= m,m ^= n,n ^= m;
    19         ans = 0;
    20         for(int x = 1;x <= n;x++)
    21         {
    22             for(int y = x;y <= m;y++)   if(gcd[x][y] <= 2)
    23             {
    24                 if(x == y)
    25                 {
    26                     int tmp = (n-x+1)*(m-y+1);
    27                     if(gcd[x][y] == 1)  ans += tmp;
    28                     else                ans -= tmp;
    29                 }
    30                 else
    31                 {
    32                     int tmp = (n-x+1)*(m-y+1);
    33                     if(x <= m && y <= n)    tmp += (m-x+1)*(n-y+1);
    34                     if(gcd[x][y] == 1)      ans += tmp;
    35                     else                    ans -= tmp;
    36                 }
    37             }
    38         }
    39         ans *= 2;
    40         printf("%lld\n",ans);
    41     }
    42 }
  • 相关阅读:
    terminal
    变量提升、函数提升
    ssh传输文件
    mocha测试框架
    npm-run 自动化
    webpack
    浅析babel
    构建工具gulp
    C++中TRACE宏及assert()函数的使用
    memcpy函数-C语言
  • 原文地址:https://www.cnblogs.com/zhexipinnong/p/3064893.html
Copyright © 2011-2022 走看看