zoukankan      html  css  js  c++  java
  • BZOJ 2301 Problem b

    AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=2301

    冬令营听了莫比乌斯,这就是宋老师上课讲的例题咯[今天来实现一下]

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 
     5 using namespace std;
     6 
     7 inline int in(){
     8     int x=0;char ch=getchar();
     9     while(ch>'9' || ch<'0') ch=getchar();
    10     while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    11     return x;
    12 }
    13 
    14 const int maxn=50010;
    15 
    16 int mu[maxn],s[maxn];
    17 int Prime[maxn],cnt;
    18 bool no_prime[maxn];
    19 
    20 void get_prime(){
    21     int tmp;mu[1]=1;
    22     for(int i=2;i<maxn;i++){
    23         if(!no_prime[i]) Prime[++cnt]=i,mu[i]=-1;
    24         for(int j=1;j<=cnt && ((tmp=Prime[j]*i)<maxn);j++){
    25             no_prime[tmp]=true;
    26             if(i%Prime[j]==0){mu[tmp]=0;break;}
    27             mu[tmp]=-mu[i];
    28         }
    29     }
    30     for(int i=1;i<maxn;i++) s[i]=s[i-1]+mu[i];
    31 }
    32 
    33 //j表示在所有数x中n/x=n/i的最后一个
    34 long long calcu(int n,int m){
    35     long long sum=0;
    36     if(n>m) swap(n,m);
    37     for(int i=1,j=0;i<=n;i=j+1){
    38         j=min(n/(n/i),m/(m/i));
    39         sum+=(long long)(s[j]-s[i-1])*(m/i)*(n/i);
    40     }
    41     return sum;
    42 }
    43 
    44 int main(){
    45 #ifndef ONLINE_JUDGE
    46     freopen("2301.in","r",stdin);
    47     freopen("2301.out","w",stdout);
    48 #endif
    49 
    50     int T,a,b,c,d,k;
    51     long long ans;
    52     
    53     get_prime();
    54     T=in();
    55     while(T--){
    56         a=in(),b=in(),c=in(),d=in(),k=in();
    57         ans=calcu(b/k,d/k)-calcu(b/k,(c-1)/k)-calcu((a-1)/k,d/k)+calcu((a-1)/k,(c-1)/k);
    58         printf("%lld
    ",ans);
    59     }
    60 
    61     return 0;
    62 }
    View Code

    [感觉还是说一下怎么做吧...]不过建议大家还是找个ppt来看好啦[我没有图啊...]

    首先将问题变成询问[i=1...n][j=1...m]中有多少gcd(i,j)==k的数

    然后其实就是[i=1...n/k][j=1...m/k]中gcd(i,j)==1的数

    然后设f(n,m,k)表示[i=1...n/k][j=1...m/k]中gcd(i,j)==1的个数

    g(n,m,k)表示[i=1...n/k][j=1...m/k]中gcd(i,j)是1的倍数的个数 <- 小学生都知道这个等于(n/k)*(m/k)是吧

    所以这一步直接由定义推来

    然后莫比乌斯反演一下

    然后再把g(n,m,k)的公式带一下

    就是这个样子了...

    然后发现有一大部分的数值是相同的,然后就可以看代码的分块了...

  • 相关阅读:
    Java并发编程:Lock
    java多线程中的生产者与消费者之等待唤醒机制@Version2.0
    java多线程中的生产者与消费者之等待唤醒机制@Version1.0
    vim 自动补全
    git 忽略文件的三种方式
    vim 查找整个工程
    vim 寄存器的使用
    我的vim插件列表
    web前端面试系列 一 js闭包
    web前端面试系列
  • 原文地址:https://www.cnblogs.com/Robert-Yuan/p/5180418.html
Copyright © 2011-2022 走看看