您的位置:首页 > 其它

HDU 2841 Visible Trees - 莫比乌斯 /容斥原理

2016-10-01 15:09 441 查看
题意:给你个m*n方格,广场格从(1,1)开始。在树中的每个点,然后让你(0,0)点往下看,问:你能看到几棵树。

其实就是对于一个矩形 (1,j) (1,j)是否对角线没经过其他点

也就是求 gcd(i,j)==1的数量

用莫比乌斯反演求一下就好

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll p =1000000007;
const int N=100000;
bool is_prime[N+500];
int prime[N+50];
int mu[N+50];
ll sum[N+50];
ll tot;
void Moblus()
{
tot = 0;
mu[1] = 1;
for(ll i = 2; i < N; i++)
{
if(!is_prime[i])
{
prime[tot++] = i;
mu[i] = -1;
}
for(ll j = 0; j < tot && i*prime[j] < N; j++)
{
is_prime[i*prime[j]] = 1;
if(i % prime[j])
{
mu[i*prime[j]] = -mu[i];
}
else
{
mu[i*prime[j]] = 0;
break;
}
}
}
}
//找[1,n],[1,m]内互质的数的对数
ll solve(ll n,ll m )
{
if (n>m)swap(n,m);
ll ret=0;
for (int i=1;i<=n;i++)
ret+=mu[i]*(n/i)*(m/i);
return ret;
}
int main()
{
Moblus();
for (int i=1;i<N;i++)
sum[i]=sum[i-1]+mu[i];
int t;cin>>t;
while(t--)
{
ll k,a,b,c,d;
scanf("%lld",&a);
scanf("%lld",&b);
ll ans1=solve(a,b);
printf("%lld\n",ans1);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: