hdu 5726 2016 Multi-University Training Contest 1(二分+dp)

来源:互联网 发布:怎样消费到淘宝v2 编辑:程序博客网 时间:2024/06/13 02:46
#include<iostream>#include<cstdio>#include<cstring>#include<map>#include<cmath>using namespace std;int n,m,dp[100005][20],a[100005];map<int,long long> mp;int gcd(int a,int b){    if(a<b)        swap(a,b);    return a%b?gcd(b,a%b):b;}int solve(int l,int r){    int temp=(int)log2(1.0*(r-l+1));    temp=gcd(dp[l][temp],dp[r-(1<<temp)+1][temp]);    return temp;}void init(){    for(int i=1;i<=n;i++)        dp[i][0]=a[i];    for(int i=1;i<20;i++)        for(int j=1;j<=n&&(j+(1<<i)-1<=n);j++)            dp[j][i]=gcd(dp[j][i-1],dp[j+(1<<(i-1))][i-1]);    for(int i=1;i<=n;i++)    {        int temp=dp[i][0],j=i;        while(j<=n)        {            temp=solve(i,j);            int l=j,r=n;            while(l<r)            {                int mid=(l+r+1)>>1;                if(solve(i,mid)==temp)                    l=mid;                else                    r=mid-1;            }            mp[temp]+=l-j+1;            j=l+1;        }    }}int main(){    int t,cnt=0,i,l,r,res;    scanf("%d",&t);    while(t--&&scanf("%d",&n)!=EOF)    {        printf("Case #%d:\n",++cnt);        mp.clear();        for(i=1;i<=n;i++)            scanf("%d",a+i);        init();        scanf("%d",&m);        while(m--&&scanf("%d%d",&l,&r)!=EOF)        {            res=solve(l,r);            printf("%d %lld\n",res,mp[res]);        }    }    return 0;}

0 0
原创粉丝点击