SPOJ10649 Mirror Number(三进制回文)
来源:互联网 发布:网络电视最清楚的软件 编辑:程序博客网 时间:2024/06/15 16:45
/*
题目:Mirror Number
题目描述:
A number is called a Mirror number if on lateral inversion, it gives the same number i.e it looks the same in a mirror. For example 101 is a mirror number while 100 is not.
Given two numbers a and b, find the number of mirror numbers in between them (inclusive of a and b).
大意:求区间[a,b]内有多少个mirror数,mirror数是左右对称的,如0,1,8,11,88,101,111,181,808,818,888等,而其他的包含有非0,1,8数位的回文数则不是;
Input
First line contains T, number of testcases <= 10^5.
Each testcase is described in a single line containing two numbers a and b.
0 <= a<=b <= 10^44
Output
For each test case print the number of mirror numbers between a and b in a single line.
解题思路:
写一个求F(0,n)区间的mirror数的个数函数,那么答案就是F(b)- F(a-1);
F函数的思路如下:
第一步找出小于等于n,且是回文的数m;
第二步找出小于等于m,且只包含0,1,8,的数x;
第三步把0,1,8看成是三进制,类似于求区间回文数(只不过回文数里面可用的数字有10个,所以是10进制),统计奇数个位和偶数个位上的个数;
最后相加就是答案;
代码:
*/
#include<stdio.h>#include<string.h>#define LL long longint ternary[10],vis[3]={8,1,0};void getCloseNum(char *num){int i,j,tag;for(i=1;i<=num[0];i++){tag=-1;for(j=0;j<3;j++){if(num[i]==vis[j])break;if(tag<0&&num[i]>vis[j]) tag=j;}if(j>=3){num[i++]=vis[tag];for(;i<=num[0];i++)num[i]=vis[0];break;}}if(tag==0){for(i=1;i<=num[0];i++)if(!num[i])tag++;else break;for(i=1;i<=num[0]-tag;i++)num[i]=num[i+tag];num[0]-=tag;}}LL cal(char *num){LL ans=0;int i;for(i=1;i<=num[0];i++){ans*=3;ans+=ternary[num[i]];}return ans+1;}void subOne(char * num){int i,ans=1;for(i=num[0];i>0;i--){num[i]-=ans;if(num[i]<0)num[i]+=10;else ans=0;}for(i=1;i<=num[0];i++) if(!num[i])ans++;else break;for(i=1;i<=num[0]-ans;i++)num[i]=num[i+ans];num[0]-=ans;if(num[0]==0)num[0]=1;}void Cp(char *a,char *b){int i;a[0]=b[0];for(i=1;i<=a[0];i++)a[i]=b[i];}LL fun(char *num,int tag){if(num[0]==0)return 0;getCloseNum(num);return cal(num)-(tag?0:1);}LL find(char *num){int i,tag;char nextbit[50];tag=num[0]&1;Cp(nextbit,num);num[0]=num[0]/2+(num[0]&1);for(i=1;i<=nextbit[0]-1;i++)nextbit[i]=9;nextbit[0]--;nextbit[0]=nextbit[0]/2+(nextbit[0]&1);return fun(num,tag)+fun(nextbit,1-tag);}void format(char *num,int has){int i,flag=0,tag;if(!has){for(i=1;num[i];i++)num[i]-='0'; num[0]=i-1;}tag=num[0]&1;for(i=1;i<=num[0]/2;i++){if(num[num[0]/2+1-i]<num[num[0]/2+tag+i]) { flag=1;break;}if(num[num[0]/2+1-i]>num[num[0]/2+tag+i]) { flag=-1;break;}}if(flag<0){for(i=2;i<=num[0]/2+tag;i++){if(num[i])break;}if(num[1]==1&&i>(num[0]/2+tag)){--num[0];for(i=1;i<=num[0];i++)num[i]=9;}else{num[0]=num[0]/2+tag;subOne(num);num[0]=2*num[0]-tag;for(i=num[0]/2+tag+1;i<=num[0];i++)num[i]=9;}}}int main(){int cas;char a[50],b[50];ternary[8]=2;ternary[1]=1;ternary[0]=0;scanf("%d",&cas);while(cas--){scanf("%s%s",a+1,b+1);format(a,0);format(b,0);if(a[1]==0&&a[0]==1){printf("%lld\n",find(b));continue;}subOne(a);format(a,1);printf("%lld\n",find(b)-find(a));}return 0;}
- SPOJ10649 Mirror Number(三进制回文)
- Mirror Number (数位dp)
- UVALive 6342 The Mirror of Galadriel (回文串)
- SPOJ MYQ10 10649. Mirror Number (数位dp)
- palindrome-number(回文数)
- Palindrome Number(回文数字)
- 回文数字(Palindrome Number)
- [LeetCode]判断回文数(Palindrome Number)
- LeetCode | Palindrome Number(回文数字)
- [LeetCode-9] Palindrome Number(回文数)
- Beautiful Palindrome Number(回文数)
- LeetCode 9. Palindrome Number(回文数字)
- 9. Palindrome Number (回文数判断)
- LeetCode之Palindrome Number(回文数)
- Leetcode#9. Palindrome Number(回文数)
- LeetCode:Palindrome Number(回文判断)
- SPOJ - MYQ10 Mirror Number (数位DP)
- SPOJ MYQ10 Mirror Number 数位dp
- Next Mayor--SOJ 2013week2.1000
- x264 windows 下用vs2010 编译
- 将一个正整数N用二进制表示并转化为一个string类型的值s
- LeetCode Generate Parentheses
- 黑马程序员_网络编程(2) TCP
- SPOJ10649 Mirror Number(三进制回文)
- SVN版本库的创建、配置与Apache的整合
- Android权限对照表
- apache和tomcat区别
- 实用设计模式之状态模式
- select返回记录的顺序
- 【性能优化】:likely和unlikely
- fedora17下root用户可以直接登陆
- 大数运算 (C++)