UVALive 3720 Highways

来源:互联网 发布:淘宝怎么做百度推广 编辑:程序博客网 时间:2024/06/03 15:57

UVALive 3720 Highways

  • 链接:UVALive 3720
  • 题意:给出一个mxn的矩形点阵,问除了水平和竖直的线,最多可以添加多少条不重复且不覆盖的连线?
  • 思路:组合数学,但是可以打表找出前几项的规律,然后dp。先遍历每个点为之前矩阵所增加的连线,然后再遍历一遍,将这些点的贡献求和再减去重复的。只求左上到右下的,根据对称性,最后结果乘以二。
    dp1[i][j]=dp1[i-1][j]+dp1[i][j-1]-dp1[i-1][j-1]+(gcd(i,j)==1);//i,j互质则说明有一条新的斜率的线
    dp2[i][j]=dp2[i-1][j]+dp2[i][j-1]-dp2[i-1][j-1]+dp1[i][j]-dp1[i/2][j/2];

下面是完整代码:

#include <cstdio>#include <iostream>#include <cstring>#include <cstdlib>#include <cmath>#include <set>#include <algorithm>#include <map>#include <bitset>#include <vector>#include <queue>#include <stack>#include <utility>#include <functional>#include <sstream>#include <list>#include <complex>#include <ctime>using namespace std;#define ll long long#define ull unsigned long longconst int MAXN=100005;const int INF=987654323;const int MOD=1e9+7;ll dp1[305][305],dp2[305][305];ll m,n;ll gcd(ll a,ll b){    return b==0?a:gcd(b,a%b);}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    for(int i=1;i<=300;i++)        for(int j=1;j<=300;j++)            dp1[i][j]=dp1[i-1][j]+dp1[i][j-1]-dp1[i-1][j-1]+(gcd(i,j)==1);    for(int i=1;i<=300;i++)        for(int j=1;j<=300;j++)            dp2[i][j]=dp2[i-1][j]+dp2[i][j-1]-dp2[i-1][j-1]+dp1[i][j]-dp1[i/2][j/2];    cin>>n>>m;    while(n||m){        cout<<(dp2[n-1][m-1]<<1)<<endl;        cin>>n>>m;    }    return 0;}

0 0
原创粉丝点击