这个题比赛的时候没做出来,本来以为枚举时间不多(我开始用的DFS+各种剪枝),但还是TLE。后面看解题报告做的,大概就是说分3种情况计算,对于进制数中位数为1,2,都比较好计算,对于位数为3的进行枚举(这里枚举就很少了)
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
int num[5]={3,4,5,6};
long long n;
int ans;
vector<int> s;
int main()
{
int T,cas=1;
scanf("%d",&T);
while(T--)
{
scanf("%I64d",&n);
s.clear();
if(n>=3&&n<=6)
{
printf("Case #%d: -1\n",cas++);
continue;
}
if(n<3)
{
printf("Case #%d: %d\n",cas++,0);
continue;
}
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
{
if((n-num[i])%num[j])
continue;
long long res=(n-num[i])/num[j];
if(res>max(num[i],num[j]))
{
s.push_back((n-num[i])/num[j]);
}
}
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
for(int k=0;k<4;k++)
{
long long l=4,r=1e6+100;
while(l<=r)
{
long long mid=(l+r)>>1;
long long val=num[i]*mid*mid+num[j]*mid+num[k];
if(val==n)
{
if(mid>num[i]&&mid>num[j]&&mid>num[k])
s.push_back(mid);
break;
}
if(val>n)
r=mid-1;
else
l=mid+1;
}
}
for(long long i=4;i*i*i<=n;i++)
{
long long val=n;
bool is=true;
while(val)
{
long long res=val%i;
if(res<3||res>6)
{
is=false;
break;
}
val/=i;
}
if(is)
{
s.push_back(i);
}
}
sort(s.begin(),s.end());
int ans=unique(s.begin(),s.end())-s.begin();
printf("Case #%d: %d\n",cas++,ans);
}
return 0;
}