题目链接:http://lightoj.com/volume_showproblem.php?problem=1399
题意:定义x的函数f(x)为x可以表示成连续数之和的种类。比如f(6)=1(6=1+2+3),f(18)=2(18=5+6+7=3+4+5+6)。现在给出P,求一个最小的x满足f(x)=P。
思路:我们知道:
(1)f(x)就是x的非1奇因子的个数;
(2)若x=p1^e1*p2^e2*……*pt^et,那么x的约数个数为(e1+1)*(e2+1)*……*(et+1)。
因此,问题转化为将P+1分解成若干数的乘积,设为k,P+1=a1*a2*……*ak,x=3^(a1-1)*5^(a2-1)*……*y^(ak-1)(y为第k个奇素数)。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#define i64 long long
#define u32 unsigned int
using namespace std;
int C,num=0;
const int MAX=1000005;
u32 tag[MAX/64+5];
int prime[MAX/10],cnt;
void init()
{
prime[cnt++]=2;
int i,j;
for(i=3;i<=MAX;i+=2) if(!(tag[i>>6]&(1<<(i/2%32))))
{
prime[cnt++]=i;
for(j=i*3;j<=MAX;j+=i*2) tag[j>>6]|=(1<<(j/2%32));
}
}
const i64 MOD=1000000007;
i64 n;
vector<i64> V;
i64 POW(i64 a,i64 b)
{
i64 ans=1;
while(b)
{
if(b&1) ans=ans*a%MOD;
a=a*a%MOD;
b>>=1;
}
return ans;
}
double Min;
i64 ans;
struct node
{
double f;
i64 p,qflag;
};
node a[150];
int cmp(node a,node b)
{
return a.f<b.f;
}
double f[2][50];
i64 q[2][4][50],p[2][50];
int pre,cur;
void DFS(int dep,int stateNum)
{
int i,j,k,t=0,r,c;
if(dep==V.size())
{
for(i=1;i<=stateNum;i++) if(f[pre][i]<Min)
{
Min=f[pre][i];
ans=p[pre][i];
}
return;
}
i64 x=V[dep];
for(i=1;i<=stateNum;i++) for(j=1;j<=V.size();j++)
{
t++;
a[t].qflag=i*100+j;
a[t].f=f[pre][i]+q[pre][i][j]*(x-1)*log(prime[j]*1.0);
a[t].p=p[pre][i]*POW(prime[j],q[pre][i][j]*(x-1))%MOD;
}
sort(a+1,a+t+1,cmp);
k=0;
for(i=1;i<=t&&k<3;i++) if(i==1||a[i].p!=a[i-1].p)
{
k++;
f[cur][k]=a[i].f;
p[cur][k]=a[i].p;
r=a[i].qflag/100;
c=a[i].qflag%100;
for(j=1;j<=V.size();j++) q[cur][k][j]=q[pre][r][j];
q[cur][k][c]*=x;
}
pre^=1;
cur^=1;
DFS(dep+1,k);
}
i64 get()
{
if(n==1) return 1;
i64 i,j,k;
V.clear();
for(i=0;i<cnt&&(i64)prime[i]*prime[i]<=n;i++)
{
while(n%prime[i]==0)
{
V.push_back(prime[i]);
n/=prime[i];
}
}
if(n>1) V.push_back(n);
for(i=0,j=V.size()-1;i<j;i++,j--)
{
k=V[i];
V[i]=V[j];
V[j]=k;
}
Min=1e40;
for(i=1;i<=V.size();i++) q[0][1][i]=1;
f[0][1]=0;
p[0][1]=1;
pre=0;cur=1;
DFS(0,1);
return ans;
}
int main()
{
init();
for(scanf("%d",&C);C--;)
{
scanf("%lld",&n);
n++;
printf("Case %d: %lld\n",++num,get());
}
return 0;
}