zoukankan      html  css  js  c++  java
  • hnu Dirichlet's Theorem

      1 /*
      2 求ax+b  x属于区间[L,R];范围内素数的个数。
      3 a*R+b<=10^12 ;  R-L+1<=10^6
      4 
      5 枚举,超时。
      6 1.如果GCD(a,b)>1 那么a+b 2*a+b ..都会是合数。此时只有判断b是否为素数。
      7 
      8 2.如果GCD(a,b)=1 那么就可以列式子
      9   ax+b %p = 0  其中p为素数。 如果满足,那么ax+b就是合数。
     10   筛选整个区间即可。
     11  
     12 由于最大的数字是10^12,只能被sqrt(10^12)的素数整除,所以筛选10^6内的素数。
     13 由于区间L,R 10^6,开一个bool hash[ ]。
     14 
     15 ax+b % py = 0  ===>  ax+py = -b;
     16 
     17 根据扩展欧几里得求出 最小的x,此时的x可以为0.  while(x<0) x+p;
     18 
     19 求出最小的x,关键还要求出第一个满足在区间[ L ,R ]里的数字。
     20 
     21 temp = L%p;
     22 x = x - temp;
     23 
     24 while(a*(L+x)+b<=p) { //关于此处等号,是一个问题 既然a*x+b 是合数,怎么会=p,加了也不会错。
     25  x = x + p;
     26 }
     27 
     28 这样的L+x就是区间[L ,R]里的第一个满足的数字。
     29 而且x可以为0,刚好用hash的时候,直接对x进行哈希。
     30 
     31 while(x<(R-L+1)){//不能等于,从0 --R-L  有 R-L+1个了。
     32 hash[x] = false;
     33 x = x+p;
     34 }
     35 
     36 3.最后求出结果。扫一遍哈希。
     37 
     38 
     39 需要注意的是,由于a*x+b <=2的情况,所以对x==0 || x<=1 进行特判。
     40 */
     41 #include<iostream>
     42 #include<stdio.h>
     43 #include<cstring>
     44 #include<cstdlib>
     45 #include<math.h>
     46 using namespace std;
     47 typedef long long LL;
     48 
     49 const int maxn = 1e6+1;
     50 int prime[maxn],len = 0;
     51 bool s [maxn];
     52 bool hash1[maxn];
     53 void init()
     54 {
     55     int i,j;
     56     memset(s,true,sizeof(s));
     57     for(i=2;i<maxn;i++)
     58     {
     59         if(s[i]==false) continue;
     60         prime[++len] = i;
     61         for(j=i*2;j<maxn;j=j+i)
     62             s[j]=false;
     63     }
     64     s[0] = s[1] = false;
     65 }
     66 bool isprime(LL n)
     67 {
     68     LL i,ans;
     69     if(n<maxn) return s[n];
     70     ans = (LL)sqrt(n*1.0);
     71 
     72     for(i=1; i<=len && prime[i]<=ans; i++)
     73     {
     74         if(n%prime[i]==0) return false;
     75     }
     76     return true;
     77 }
     78 LL Ex_GCD(LL a,LL b,LL &x,LL& y)
     79 {
     80     if(b==0)
     81     {
     82         x=1;
     83         y=0;
     84         return a;
     85     }
     86     LL g=Ex_GCD(b,a%b,x,y);
     87     LL hxl=x-(a/b)*y;
     88     x=y;
     89     y=hxl;
     90     return g;
     91 }
     92 int main()
     93 {
     94     LL a,b,L,U,x,y;
     95     LL i,p;
     96     int t = 0;
     97     init();
     98     while(scanf("%I64d",&a)>0)
     99     {
    100         if(a==0)break;
    101         scanf("%I64d%I64d%I64d",&b,&L,&U);
    102         LL g = Ex_GCD(a,b,x,y);
    103         if(g>1)
    104         {
    105             if(L==0 && isprime(b))
    106                 printf("Case %d: 1
    ",++t);
    107             else printf("Case %d: 0
    ",++t);
    108         }
    109         else if(g==1)/** gcd(a,b) == 1   **/
    110         {
    111             memset(hash1,true,sizeof(hash1));
    112             if(L==0)
    113                 hash1[0] = isprime(b);
    114             if(L<=1)
    115                 hash1[1-L] = isprime(a+b);
    116             LL length = U-L+1;
    117             LL MAX = a*U+b;
    118             for(i=1; i<=len; i++)
    119             {
    120                 p = prime[i];
    121                 if(a%p==0)continue;
    122                 if(p*p>MAX)break;;
    123 
    124                 g = Ex_GCD(a,p,x,y);// ax+py = -b;
    125                 x = (x*-b) % p;
    126                 while(x<0) x=x+p;
    127 
    128                 LL temp = L%p;
    129                 x = x - temp;
    130                 while(x<0) x=x+p;
    131 
    132                 while(a*(x+L)+b<=p)
    133                 {
    134                     x = x+p;
    135                 }
    136                 while(x<length)
    137                 {
    138                     hash1[x]=false;
    139                     x=x+p;
    140                 }
    141             }
    142             LL hxl = 0;
    143             for(i=0; i<length; i++) if(hash1[i]==true) hxl++;
    144             printf("Case %d: %I64d
    ",++t,hxl);
    145         }
    146     }
    147     return 0;
    148 }
  • 相关阅读:
    【leetcode】328 Odd Even Linked List
    【leetcode】86 partition list
    【leetcode】92 Reverse Linked List II
    【leetcode】220 ContainsDuplicate3
    【leetcode】219 Contains Duplicate2
    【leetcode】149 Max Points on a Line
    Java实现验证码图片
    求解两点(经纬度坐标)的距离
    POI开源项目-PPT2PNG转换测试
    编程内功修炼之设计模式—责任链模式
  • 原文地址:https://www.cnblogs.com/tom987690183/p/3863308.html
Copyright © 2011-2022 走看看