【51Nod 1180】方格射击游戏

来源:互联网 发布:python urlopen 重试 编辑:程序博客网 时间:2024/04/30 01:51

Description

M*N的方格矩阵,一个人在左下角格子的中心,除他所站位置外,其他格子的中心都有一个敌人,他一次可发射一枚子弹干掉一条直线上的所有敌人,问至少要发射多少子弹才能干掉所有敌人。

Solution

在一条直线上如果经过了两个点及以上,那么第一个经过的点一定是互质的,因为经过的第一个点的斜率就可以确定,如果不是互质,那么肯定是在前面确定的。
所以答案等于2+n1i=1m1j=1gcd(i,j)=1,就是互质的数对的个数。
为什么是+2,因为横着打和竖着打的斜率是0,所以要另外考虑。
为什么是n-1和m-1,因为我们枚举的只是斜率的纵长和横长而已。
那么上面的东西要怎么求呢?
很简单的莫比乌斯繁衍一下就可以了,而且还是用求f(1),我连分块都没打。

Code

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;typedef long long ll;const int maxn=5000007;ll i,j,kl,l,t,n,m,ans;ll miu[maxn],p[maxn];bool bz[maxn];int main(){    miu[1]=1;    fo(i,2,maxn-7){        if(!bz[i]){            miu[i]=-1;            p[++p[0]]=i;        }        fo(j,1,p[0]){            t=i*p[j];            if(t>maxn-7)break;            bz[t]=1;            if(i%p[j]==0)break;            miu[t]=-miu[i];        }    }    scanf("%lld%lld",&n,&m);n--;m--;    if(n>m)swap(n,m);    fo(i,1,n){        ans+=(n/i)*(m/i)*miu[i];    }    if(n>0)ans++;if(m>0)ans++;    printf("%lld\n",ans);}
2 0
原创粉丝点击