一开始以为是个搜索题,还推出了很强的减枝。。然并卵,T=100教我做人
没想到是个折半后hash,挺神奇的,根据规律和感觉y大概最多10位数,因为当y很大的时候,每多1位数最多加上9^9,而整个y要*10,所以y一大了x就很容易小于0,而此题x>0,x<10^9,于是猜想y最多10位数。于是先把前5位数(可以是0)的结果保存起来,再用后5位数去搜。
用mapT掉了,于是换成了unordered_map,时间就过了,还有一个考试的时候发现的坑,就是x=0,然而y是positive interger,所以当x=0时,y=0是不行的,于是就特判一下。今天晚上做的时候忘了,调了好久。。。。还可以用数组保存结果排序后遍历数组做。
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
#define maxl 1000010
using namespace std;
int x,k,ans;
long long mi[10];
long long num1[maxl],num2[maxl];
long long qp(long long a,long long b)
{
long long ans=1,cnt=a;
while(b)
{
if(b&1)
ans=ans*cnt;
cnt=cnt*cnt;
b>>=1;
}
return ans;
}
void prework()
{
scanf("%d%d",&x,&k);mi[0]=0;
for(int i=1;i<=9;i++)
mi[i]=qp(i,k);
}
void mainwork()
{
long long sum1,sum2;
ans=0;
//dfs(0,0,1);
// m.clear();
for(int i=0;i<=99999;i++)
{
sum2=mi[i/10000]+mi[(i/1000)%10]+mi[(i/100)%10]+mi[(i/10)%10]+mi[i%10];
num1[i]=x-sum2+i;
}
sort(num1,num1+100000);
for(long long i=0;i<=99999;i++)
{
sum1=mi[i/10000]+mi[(i/1000)%10]+mi[(i/100)%10]+mi[(i/10)%10]+mi[i%10];
num2[i]=sum1-i*100000;
}
sort(num2,num2+100000);
int l=0,r=0;
while(num1[l]<num2[0] && l<=99999)
l++;
r=l;
while(num1[l]==num2[0] && r<=99999)
r++;
ans+=r-l;
for(int i=1;i<=99999;i++)
{
if(num2[i]==num2[i-1])
{
ans+=r-l;
continue;
}
else
l=r;
while(num1[l]<num2[i] && l<=99999)
l++;
r=l;
while(num1[r]==num2[i] && r<=99999)
r++;
if(r>l && l<=99999 && r<=99999)
ans+=r-l;
}
if(x==0)
ans--;
}
void print(int cas)
{
printf("Case #%d: %d\n",cas,ans);
}
int main()
{
int cas;
scanf("%d",&cas);
for(int i=1;i<=cas;i++)
{
prework();
mainwork();
print(i);
}
return 0;
}
#include<cstdio>
#include<cstring>
#include<map>
#include <unordered_map>
using namespace std;
int x,k,ans;
long long mi[10];
unordered_map <long long,int> m;
long long qp(long long a,long long b)
{
long long ans=1,cnt=a;
while(b)
{
if(b&1)
ans=ans*cnt;
cnt=cnt*cnt;
b>>=1;
}
return ans;
}
void prework()
{
scanf("%d%d",&x,&k);mi[0]=0;
for(int i=1;i<=9;i++)
mi[i]=qp(i,k);
}
void mainwork()
{
long long sum1,sum2;
ans=0;
m.clear();
for(int i=0;i<=99999;i++)
{
sum2=mi[i/10000]+mi[(i/1000)%10]+mi[(i/100)%10]+mi[(i/10)%10]+mi[i%10];
m[x-sum2+i]++;
}
if(m.count(0));
ans+=m[0];
if(x==0)
ans--;
for(long long i=1;i<=99999;i++)
{
sum1=mi[i/10000]+mi[(i/1000)%10]+mi[(i/100)%10]+mi[(i/10)%10]+mi[i%10];
if(m.count(sum1-i*100000))
ans+=m[sum1-i*100000];
}
}
void print(int cas)
{
printf("Case #%d: %d\n",cas,ans);
}
int main()
{
int cas;
scanf("%d",&cas);
for(int i=1;i<=cas;i++)
{
prework();
mainwork();
print(i);
}
return 0;
}