【xsy2504】farm 容斥原理
题目大意:给你三个数$n,m,s$,满足$n,m,s≤10^{18}$且最大质因数均不大于$10^6$。
问你存在多少个整数$k$,满足$0≤k≤m$,且$(k,0)$,$(0,n)$,$(x,y)$组成的三角形面积为$s$,其中$x,y$均为整数。
同时,问你存在多少个整数$p$,满足$0≤p<n$,且$(0,0)$,$(0,p)$,$(x,y)$组成的三角形面积为$s$,其中$x,y$均为整数。
请输出两个问题的和。
不超过1000组数据。
对于第一个问题,我们列出三角形面积的式子
s=(s黄+s灰+s蓝+s红)-s灰-s红-s蓝
$s=|\frac{1}{2}nk-\frac{1}{2}x(n-y)-xy-\frac{1}{2}y(k-x)|$
经过化简,有$|k(y-n)+nx|=2s$
若方程有整数解,则有$gcd(k,n)|2s$
我们设$N[i]$表示数字$n$中出现了多少个质因数$p[i],K[i],S[i]$同理。
若$N[i]>S[i]$,那么有$K[i]≤S[i]$。
基于这个性质,我们就可以通过容斥原理来求了,详见代码。
考虑第二个问题,第二个问题显然是求$s$的约数个数,随便搜一下就可以了。
时间复杂度:$O(2^{16}+\sigma(10^{18}))$
1 #include<bits/stdc++.h> 2 #define MM 1000005 3 #define NN 80000 4 #define L long long 5 using namespace std; 6 7 L pow_mod(L x,L k){L ans=1; for(;k;k>>=1,x=x*x) if(k&1) ans=ans*x; return ans;} 8 9 int pri[MM]={0},b[MM]={0},use=0,last[MM]={0},id[MM]={0}; 10 void init(){ 11 for(int i=2;i<MM;i++){ 12 if(!b[i]) pri[++use]=i,last[i]=1,id[i]=use; 13 for(int j=1;j<=use&&i*pri[j]<MM;j++){ 14 b[i*pri[j]]=1; last[i*pri[j]]=i; 15 if(i%pri[j]==0) break; 16 } 17 } 18 } 19 20 int M[NN]={0},N[NN]={0},S[NN]={0}; 21 L a[MM]={0},m,n,s,ans=0,hh=0; 22 23 void rd(L &res,int cnt[]){ 24 res=1; 25 for(int i=0;i<3;i++){ 26 int x; scanf("%d",&x); 27 for(res*=x;x>1;x=last[x]) 28 cnt[id[x/last[x]]]++; 29 } 30 } 31 void dfs(L x,L id){ 32 if(id==hh) 33 return void(ans+=(x<=n)); 34 int ID=a[id]; 35 for(int i=0;i<=S[ID];i++){ 36 dfs(x,id+1); 37 x=x*pri[ID]; 38 } 39 } 40 void solve(){ 41 memset(M,0,sizeof(M)); memset(N,0,sizeof(N)); memset(S,0,sizeof(S)); ans=hh=0; 42 rd(n,N); rd(m,M); rd(s,S); 43 s<<=1; S[1]++; 44 for(int i=0;i<NN;i++) if(N[i]>S[i]) a[hh++]=pow(pri[i],S[i]+1); 45 for(int i=0;i<(1<<hh);i++){ 46 L mul=1,zf=1; 47 for(int j=0;j<hh;j++) 48 if(i&(1<<j)){ 49 mul=mul*a[j]; zf=-zf; 50 } 51 ans=ans+(m/mul)*zf; 52 } 53 hh=0; for(int i=0;i<NN;i++) if(S[i]) a[hh++]=i; 54 dfs(1,0); 55 printf("%lld\n",ans); 56 } 57 58 int main(){ 59 init(); 60 int t; cin>>t; 61 while(t--) solve(); 62 }