您的位置:首页 > 其它

【51Nod 1180】方格射击游戏

2016-10-20 19:55 169 查看

Description

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

Solution

在一条直线上如果经过了两个点及以上,那么第一个经过的点一定是互质的,因为经过的第一个点的斜率就可以确定,如果不是互质,那么肯定是在前面确定的。

所以答案等于2+∑n−1i=1∑m−1j=1(gcd(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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: