UVALive

来源:互联网 发布:2004年流行的网络歌曲 编辑:程序博客网 时间:2024/06/11 20:53

题意:

给n*m的点阵,问有多少条线通过至少两个点,且不竖直,不水平。


题解:

       首先,由于\这个斜线的数目和/的数目是相同的,所以我们只需计算\的数目然后×2即可。

      用d[i][j]保存从左上角(0,0)到(i,j)这个矩形中从(0,0)出发的线总数,可以发现当gcd(i,j)==1时,从(0,0)到(i,j)这条直线在该矩形中没有重复。

       所以d[i][j]=d[i-1][j]+d[i][j-1]-d[i-1][j-1]+(gcd(i,j)==1);

       那么我们求出左上角(0,0)到(i,j)这个矩形内从(0,0)出发的线数有什么用呢?

       接下来我们用pre[i][j]来保存从(0,0)到(i,j)这个矩形中所有的可行线数目,我们发现每多一个新的点(i,j),pre[i][j]=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1]+(经过(i,j)且在(0,0)到(i,j)这个矩形内的可行线数目)。

       那么这个数目怎么求呢?我们先前d[i][j]保存的是从(0,0)出发,其实从(0,0)出发等价于从(i,j)出发,因为矩形相同。

       所以pre[i][j]=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1]+d[i][j]。。?其实不是,还有重复,什么情况会重复呢?从(i,j)出发的线是否在之前就已经算在之内了呢?

       我们可以发现:线重复的充要条件是从(i,j)出发的线至少经过了该矩形中另外两个点

       那么怎么去掉呢?

       我们发现这种线的数目必定是在d[i/2][j/2]里面,因为线的长度起码要乘2才会经过另外一个点,并且d[i/2][j/2]中所有的线都会重复,因为里面线的长度都起码可以×2,而只要长度×一个大于1的数,他必定可以经过另外一个点。而先前gcd(i,j)==1这个条件,是让线在d[i][j]中没有重复。

所以最终pre[i][j]=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1]+d[i][j]-d[i/2][j/2];



#include <iostream>#include <string>#include <cstring>#include <cstdio>#include <queue>#include <map>#include <stack>#include <algorithm>#include <vector>#include <cmath>#include <set>#include <iomanip>#include <sstream>#include <ctime>#define dep(a,b,c) for(int a=b;a>=c;a--)#define rep(a,b,c) for(int a=b;a<=c;a++)#define mem(a,b) memset(a,b,sizeof(a))#define IO ios::sync_with_stdio(false)#define pb push_back#define debug(x) cout<<"["<<x<<"]"<<endl#define lson id<<1,l,mid#define rson id<<1|1,mid+1,rusing namespace std;typedef long long ll;typedef unsigned long long ull;const int INF = 0x3f3f3f3f;const ll INFLL = 0x3f3f3f3f3f3f3f3f;const int MOD = 1e9+7;const int MAXN= 3e2+5;int d[MAXN][MAXN];int pre[MAXN][MAXN];int main() {    int n,m;    rep(i,1,300)        rep(j,1,300)            d[i][j]=d[i-1][j]+d[i][j-1]-d[i-1][j-1]+(__gcd(i,j)==1);    rep(i,1,300)        rep(j,1,300)            pre[i][j]=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1]+d[i][j]-d[i/2][j/2];    while(~scanf("%d%d",&n,&m)){        if(!n&&!m)break;        printf("%d\n",pre[n-1][m-1]*2);    }}


原创粉丝点击