3505: [Cqoi2014]数三角形 组合数学

来源:互联网 发布:南京软件 外包公司 编辑:程序博客网 时间:2024/04/30 15:42

找规律就行了。。
首先所有的情况是C((n+1)*(m+1),3)。
水平+竖直共线的情况是(n+1)*C(m+1,3)+(m+1)*C(n+1,3).
剩下的就是斜着的情况:枚举i,j,代表两点为(1,i),(j,1)。然后令d=gcd(i,j),那么两点之间一定有d-1个点(所以要保证d>=2),那么现在不合法的情况有2*(d-1)(n+1-i)(m+1-j)。注意有两个方向所以要*2。

#include<iostream>#include<cstdio>#define ll long longusing namespace std;int n,m;ll ans;ll c[1002005][4];inline int read(){    int a=0,f=1; char c=getchar();    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}    return a*f;}inline void C(){    c[0][0]=1;    for (int i=1;i<=(n+1)*(m+1);i++)    {        c[i][0]=1;        for (int j=1;j<=3;j++)            c[i][j]=c[i-1][j]+c[i-1][j-1];    }}int gcd(int a,int b){    return b==0?a:gcd(b,a%b);}int main(){    n=read(); m=read();    C();    ans=c[(n+1)*(m+1)][3]-(n+1)*c[m+1][3]-(m+1)*c[n+1][3];    for (int i=1;i<=n;i++)        for (int j=1;j<=m;j++)        {            int d=gcd(i,j);            if (d>=2) ans-=2*(d-1)*(n+1-i)*(m+1-j);        }    cout << ans;    return 0;}
0 0
原创粉丝点击