[莫比烏斯反演] bzoj2301: [HAOI2011]Problem b
阿新 • • 發佈:2019-02-16
因為不保證a,c=1 減掉1~a和1~d 1~c和1~b 的匹配 然後把重複的1~a和1~c的匹配加回來
然後就T掉了nice!
加一個分塊加速
因為有很大一段的(b/i) (d/i) 是一樣的
就相當於乘法分配率
U[ ]用上字首和之後 直接瞎跳小的那個就ok
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int prime[51000],mu[51000],pr;//mu:反演時的係數(容斥)
bool v[110000];
void get_mu()
{
memset (v,1,sizeof(v));
mu[1]=1;mu[0]=0;
for (int i=2;i<=50000;i++)
{
if (v[i]==true)
{
prime[++pr]=i;
mu[i]=-1;//1個也是奇數個
}
for(int j=1;j<=pr&&prime[j]*i<=50000;j++)
{
v[prime[j]*i]=0;
if (i%prime[j]==0)
{
mu[i*prime[j]]=0 ; //i包含了prime[j] e>1
break;
}
else
{
mu[i*prime[j]]=-mu[i];//奇變偶 偶變奇
}
}
mu[i]+=mu[i-1];//字首和
}
}
long long get(int a,int b)
{
long long ans=0;
int next=0;
int c=min(a,b);
for (int i=1 ;i<=c;i=next+1)
{
next=min(a/(a/i),b/(b/i));
ans+=(long long)(mu[next]-mu[i-1])*(a/i)*(b/i);
}
return ans;
}
int main()
{
//F(t)=gcd(x,y)%t==0 的x,y個數 =gcd(x,y) 的倍數的個數 F(6)=f(1)+f(2)+f(3)+f(6);
//f(t)=gcd(x,y)=t 的x,y個數 = t的gcd個數 此時由f(t) 推回F(t) 這就是反演公式 F(t)=(b/t)*(b/t)
//如果gcd(x,y)=1 gcd(x*k,,y*k)=k 直接除掉 k 然後求 f(1) 然後 x,y在1~b選的時候可能會有重(gcd(2,3)=gcd(3,2)) /2去重
get_mu();
int t;
scanf("%d",&t);
while (t--)
{
int a,b,c,d,k;
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
if (k==0) {printf("0\n");continue;}
a=(a-1)/k;b/=k;c=(c-1)/k;d/=k;k=1;
long long ans1=0,ans2=0,ans3=0,ans4=0,ans5=0;
ans1=get(b,d);
ans3=get(a,d);//1~a 和 1~d 匹配
ans4=get(c,b);//1~c 和 1~b 匹配
ans5=get(a,c);//1~a 和 1~c 匹配
printf("%lld\n",ans1-ans3-ans4+ans5);
}
return 0;
}