zoukankan      html  css  js  c++  java
  • 【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
    ",ans);
    56 }
    57 
    58 int main(){
    59     init();
    60     int t; cin>>t;
    61     while(t--) solve();
    62 }
  • 相关阅读:
    简单工厂模式
    设计模式概述
    Excel中如何按单元格颜色求和,这五种牛批的方法,值得学习
    Excel数据透视表只能求和运算?快来学习求差运算小技巧
    如何在Excel中分组排名?两个公式轻松搞定!
    开始菜单之数字格式,这些基础知识还记得吗?
    2021,我来了
    2020年会必备,Excel轻松制作抽奖小游戏
    如何用Excel制作工作计划,跟踪任务进度,快来学习吧
    如何防止Excel数据录入出错,巧用数据验证,实现自动限制录入
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10556490.html
Copyright © 2011-2022 走看看