【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 }

 

posted @ 2019-03-19 09:05  AlphaInf  阅读(158)  评论(0编辑  收藏  举报