zoukankan      html  css  js  c++  java
  • hdu5726-GCD-ST表+二分

    先用st表处理出所有l-r的GCD值,然后二分求得这些值一共出现了多少次。

      1 #include<bits/stdc++.h>
      2 
      3 #define inf 0x3f3f3f3f
      4 
      5 const int maxn=100000;
      6 
      7 using namespace std;
      8 
      9 typedef pair<int,int> P;
     10 
     11 int l,r;
     12 
     13 int icase;
     14 
     15 int t,n,q;
     16 
     17 int a[maxn+1];
     18 
     19 int dp[maxn+1][20];
     20 
     21 map<int,long long> m;
     22 
     23 int gcd(int a,int b){
     24    return b==0?a:gcd(b,a%b);
     25 }
     26 
     27 void RMQ(){
     28    for(int i=1;i<=n;i++){
     29         dp[i][0]=a[i];
     30    }
     31    for(int j=1;j<20;j++){
     32         for(int i=1;i<=n;i++){
     33                 if(i+((1<<(j-1))-1)<=n)
     34                 dp[i][j]=gcd(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
     35                 //printf("%d
    ",dp[i][j]);
     36         }
     37    }
     38 }
     39 
     40 int query(int l,int r){
     41     int k=(int)log2(double(r-l+1));
     42     return gcd(dp[l][k],dp[r-(1<<k)+1][k]);
     43 }
     44 
     45 void Cal(){
     46    for(int i=1;i<=n;i++){
     47         int GCD=a[i],tail=i;
     48         while(tail<=n){
     49              int lb=tail,ub=n,mid=(lb+ub)>>1;
     50              while(ub-lb>1){
     51                 mid=(lb+ub)>>1;
     52                 if(query(i,mid)==GCD) lb=mid;
     53                 else ub=mid;
     54              }
     55              if(query(i,ub)==GCD){
     56                 m[GCD]+=(ub-tail+1);
     57                 tail=ub+1;
     58                 GCD=query(i,tail);
     59              } else if(query(i,mid)==GCD){
     60                 m[GCD]+=(mid-tail+1);
     61                 tail=mid+1;
     62                 GCD=query(i,tail);
     63              }
     64                else{
     65                 m[GCD]+=(lb-tail+1);
     66                 tail=lb+1;
     67                 GCD=query(i,tail);
     68              }
     69         }
     70    }
     71 }
     72 
     73 void solve(){
     74   scanf("%d",&n);
     75   for(int i=1;i<=n;i++){
     76         scanf("%d",&a[i]);
     77   }
     78   RMQ();
     79   Cal();
     80   scanf("%d",&q);
     81   printf("Case #%d:
    ",++icase);
     82   while(q--){
     83         scanf("%d%d",&l,&r);
     84         int res=query(l,r);
     85         printf("%d %I64d
    ",res,m[res]);
     86   }
     87 }
     88 
     89 void init(){
     90   m.clear();
     91   memset(dp,0,sizeof(dp));
     92 }
     93 
     94 int main()
     95 {
     96     scanf("%d",&t);
     97     while(t--){
     98         init();
     99         solve();
    100     }
    101     return 0;
    102 }
  • 相关阅读:
    (Java实现) 洛谷 P1603 斯诺登的密码
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1028 数的计算
    (Java实现) 洛谷 P1028 数的计算
    (Java实现) 洛谷 P1553 数字反转(升级版)
    8.4 确定两个日期之间的月份数或年数
    (Java实现) 洛谷 P1553 数字反转(升级版)
  • 原文地址:https://www.cnblogs.com/GeniusYang/p/5769572.html
Copyright © 2011-2022 走看看