有人说:人类是自己一步步进化的,而数学是上帝亲手创造的。度度熊最近也正沉醉于数学之美中,它发现了一种神奇的数字,取名曰:魔法因子。
将因子记为X,如果有一些整数与这些因子做乘法后,结果仍然是整数,同时,结果数字的首位和末位会换交换位置,而其他位置上的数字恰好不变!这时X被认为是一个魔法因子。需要注意的是,用来相乘的这些整数不会含有前导0,但是如果交换的结果有前导0,又恰好是乘法的结果,这时仍然认为X是这个整数的魔法因子。度度熊认为1不是个魔法因子,因为所有的数都可以符合这个条件,这一点都不好玩。
比如,X = 3.1312,有1875 * 3.1312 = 5871。
度度熊现在希望知道对于一个因子X,究竟有多少个整数可以满足这个条件,使其成为魔法因子。由于它还不会长度超过10位数的乘法,只需要求出长度不超过10的整数即可。
将因子记为X,如果有一些整数与这些因子做乘法后,结果仍然是整数,同时,结果数字的首位和末位会换交换位置,而其他位置上的数字恰好不变!这时X被认为是一个魔法因子。需要注意的是,用来相乘的这些整数不会含有前导0,但是如果交换的结果有前导0,又恰好是乘法的结果,这时仍然认为X是这个整数的魔法因子。度度熊认为1不是个魔法因子,因为所有的数都可以符合这个条件,这一点都不好玩。
比如,X = 3.1312,有1875 * 3.1312 = 5871。
度度熊现在希望知道对于一个因子X,究竟有多少个整数可以满足这个条件,使其成为魔法因子。由于它还不会长度超过10位数的乘法,只需要求出长度不超过10的整数即可。
Input
第一行一个整数T,表示包含T组数据。
每组数据包含一个实数 X(0<X<10,X≠1) ,同时为了避免精度问题,小数点后的数字不会超过6位。
每组数据包含一个实数 X(0<X<10,X≠1) ,同时为了避免精度问题,小数点后的数字不会超过6位。
Output
每组数据,对于每组数据,先输出一行
Case #i:
然后输出符合条件的整数的个数,如果个数不为0,在第二行输出所有符合条件的整数,按数字大小升序排列,用空格隔开,如果个数为0,只输出一行。
Case #i:
然后输出符合条件的整数的个数,如果个数不为0,在第二行输出所有符合条件的整数,按数字大小升序排列,用空格隔开,如果个数为0,只输出一行。
Sample Input
3 3.1312 3.1415 0.3
Sample Output
Case #1: 3 1875 1876875 1876876875 Case #2: 0 Case #3: 2 1428570 2857140
http://acm.hdu.edu.cn/showproblem.php?pid=5255
思路:设符合条件的数的最高位是h,最低位是l,中间不变的部分为mid,由题意可得到下面的公式(这里对X乘上1e6用a表示,b表示1e6)
(h*power+l+mid)*a=(l*power+h+mid)*b
可推得:mid=((h*power+l)*a-(l*power+h)*b)/(a-b);
所以可以枚举h,l然后求mid,注意mid的最低位一定是0,因为留出最低位加l或者h (转载)
这里要注意一点:把小数乘10^n化成整数这一步是必不可少的,因为后面mid是longlong还有取余都是要用到整数的。
p=round(x*MG),g=__gcd(p,MG) ,round()是四舍五入。
#include<iostream>
#include<algorithm>
#include<string>
#include<map>
#include<vector>
#include<cmath>
#include<queue>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#define eps 1e-6
#define ll long long
using namespace std;
ll pw[15];
vector<ll> x;
void init()
{
pw[0]=1;
for(int i=1;i<12;i++)
pw[i]=pw[i-1]*10;
}
int main(){
init();
int t;
scanf("%d",&t);
int cntt=0;
while(t--){
x.clear();
double w;
scanf("%lf",&w);
ll n=w*pw[6]+eps; //这里+eps必不可少
for(int k=2;k<=10;++k){ //k是这个数的长度
for(int i=1;i<=9;++i){ //首
for(int j=0;j<=9;++j){ //尾
ll mid=(pw[k-1]*j+i)*pw[6]-(pw[k-1]*i+j)*n;
if(mid%(10*(n-pw[6]))==0){ //注意*10
mid/=(n-pw[6]);
if(mid<0) //这里要特别注意!mid是有可能小于0的!!
continue;
int cnt=0;
ll q=mid;
while(q){
cnt++;
q/=10;
}
if(cnt<=k-1)
x.push_back(i*pw[k-1]+mid+j);
}
}
}
}
printf("Case #%d:\n",++cntt);
printf("%d\n",x.size());
if(x.size()==0)
continue;
for(int i=0;i<x.size()-1;++i)
cout<<x[i]<<" ";
cout<<x[x.size()-1]<<endl;
}
return 0;
}
#include<iostream>
#include<algorithm>
#include<string>
#include<map>
#include<vector>
#include<cmath>
#include<queue>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#define ll long long
#define N (1<<4)
#define MG 1000000ll
using namespace std;
double x;
int T,cas;
ll pw[N]={1};
vector<ll> res;
void init()
{
for(int i=1;i<12;i++)
pw[i]=pw[i-1]*10;
}
bool judge(ll x,ll y,int n)
{
if(x<pw[n] || x>=pw[n+1]) return 0;
ll a=x/pw[n],b=x%10,c=x-a*pw[n]-b;
return y==b*pw[n]+c+a;
}
int main()
{
init();
for(cin>>T;T--;)
{
res.clear();
scanf("%lf",&x);
ll p=round(x*MG),g=__gcd(p,MG),q=MG/g; p/=g; //round四舍五入
for(int i=1;i<=9;i++)
for(int j=-9;j<=9;j++)
if((pw[i]*j-j)%(q-p)==0)
{
ll t=(pw[i]*j-j)/(q-p);
if(judge(t*q,t*p,i)) //这里就是直接反转,判断
res.push_back(t*q);
}
sort(res.begin(),res.end());
printf("Case #%d:\n%d\n",++cas,res.size());
if(res.size())
{
for(int i=0;i<res.size()-1;i++)
printf("%I64d ",res[i]);
printf("%I64d\n",*(res.rbegin()));
}
}
return 0;
}