HDU6156 Palindrome Function(回文数)

来源:互联网 发布:head first php怎么样 编辑:程序博客网 时间:2024/05/01 16:37
#include <iostream>#include <cstdio>#include <algorithm>using namespace std;/*k进制下的回文数如果n在k进制下是回文数f(n,k)=k,否则f(n,k)=1n和k的变化范围为L<=n<=R,l<=k<=r,计算f(n,k)的累加和对于一个数,比如k进制下,从高位到地位表示为,456123k[]=321654、x=654、y=123、len=6由于x>y,那么最大回文数应该为455554否则,最大的回文数应该是456654,对于后面的个数需要-1个在len=6时,最小的回文数为100001,也就是len=6时回文数的个数为(456-100+1)-1个*/long long dp[40][50];//在i进制下j位数的回文数个数//xx为允许最大的数,上限,p为进制,也是当前进制下每个回文数的权值long long slove(long long xx,long long p){    long long ans=0;//0-xx 在p进制下回文数个数    if(xx==0)        return 0;    int k[500];    int len=0;//p进制表示时,数的位数    long long q=xx;    while(q)//在p进制下分解    {        k[len++]=q%p;        q/=p;    }    if(len==1)        return xx*p;//回文的个数*每个回文数权值        long long x=0,y=0,z=0;    if(len%2==0)//位数为偶数    {        //当前这个数分为前后两个部分        for(int i=len/2;i<len;i++)//计算前一半数倒置的大小            x=x*p+k[i];        for(int i=len/2-1;i>=0;i--)//计算后一半数的大小            y=y*p+k[i];        int flay=0;        if(x>y)//前面一个数的倒置比后一个数大            flay=-1;        z=k[len-1]-1;//z为k进制时,xx这个数回文数的个数,少了1个        for(int i=len-2;i>=len/2;i--)            z=z*p+k[i];        z+=flay;//最大的那个回文数不可能的情况        ans=z+1;//+1个        for(int i=1;i<len;i++)            ans+=dp[p][i];    }    else    {        for(int i=len/2+1;i<len;i++)            x=x*p+k[i];        for(int i=len/2-1;i>=0;i--)            y=y*p+k[i];        int flay=0;        if(x>y)            flay=-1;        z=k[len-1]-1;        for(int i=len-2;i>=len/2;i--)            z=z*p+k[i];        z+=flay;        ans=z+1;        for(int i=1;i<len;i++)            ans+=dp[p][i];    }    return ans*p+xx-ans;//回文个数*每个回文权值+(数总的个数-回文个数)*1(不是回文权值)}int main(){    int t;    scanf("%d",&t);    for(int i=2;i<=36;i++)//i进制    {        dp[i][1]=i-1;        dp[i][2]=i-1;        for(int j=4;j<=32;j+=2)//在i进制下,数的位数为j        {            dp[i][j]=dp[i][j-2]*i;            dp[i][j-1]=dp[i][j];            if(dp[i][j]>=1000000000)                break;        }    }    int cas=0;    while(t--)    {        long long L,R,l,r;        long long ans=0;        scanf("%lld%lld%lld%lld",&L,&R,&l,&r);        for(int i=l;i<=r;i++)//枚举进制        {            ans+=slove(R,i);            ans-=slove(L-1,i);        }        printf("Case #%d: %lld\n",++cas,ans);    }}
原创粉丝点击