题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=2833
题解
显然,每种情况都可以转化成:的取值为与XXX......XXX......XXX......
类似的情况,其中位置为X
说明中有,否则没有。
设表示取值范围长度为,需要选个值,时连续X
长度为,时连续X
长度大于,此时的方案数。
状态数不多,用记搜,map记录状态。
代码
#include <map>
#include <cstdio>
#include <algorithm>
int read()
{
int x=0,f=1;
char ch=getchar();
while((ch<'0')||(ch>'9'))
{
if(ch=='-')
{
f=-f;
}
ch=getchar();
}
while((ch>='0')&&(ch<='9'))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int maxn=1000;
struct data
{
int len,n,k;
data(int _len=0,int _n=0,int _k=0):len(_len),n(_n),k(_k){}
bool operator <(const data &other) const
{
if(len==other.len)
{
if(n==other.n)
{
return k<other.k;
}
return n<other.n;
}
return len<other.len;
}
};
std::map<data,long long> f;
long long getf(data d)
{
if(d.n==1)
{
return 1-d.k;
}
if(f.count(d))
{
return f[d];
}
if(d.k==0)
{
f[d]=getf(data(d.len,d.len/d.n,1));
}
else
{
long long ans=0;
for(int i=1; i*i<=d.n; ++i)
{
if(d.n%i)
{
continue;
}
if(i!=1)
{
ans+=getf(data(d.len/i,d.n/i,0));
}
if(i*i!=d.n)
{
ans+=getf(data(d.len/(d.n/i),d.n/(d.n/i),0));
}
}
f[d]=ans;
}
return f[d];
}
int t,n;
int main()
{
t=read();
while(t--)
{
n=read();
if(n==1)
{
puts("1");
continue;
}
printf("%lld\n",getf(data(n*n,n,1)));
}
return 0;
}