题解 【P6267 [SHOI2002]N的连续数拆分】
[SHOI2002]N的连续数拆分【数据加强版】
来一个和其它题解稍稍有些不一样的做法。
首先还是列出等式,设最小的正整数为
化简一下第二个式子便是
显然当
int work (ll x)
{
int cnt = 0;
x <<= 1;
for (ll i = 2;i * i <= x;++i)//记得为 long long
if (x % i == 0)
if ((i + x / i) & 1) ++cnt;
return cnt;
}
那么还有没有更优的解法呢??
我们观察
先将
//这个方法在多组数据中会更优
#include <iostream>
#include <cstdio>
#include <cmath>
#define ll long long
using namespace std;
const int MAX = 3e7 + 5;
int cnt,p[MAX >> 1];//p 记录质数,显然 sqrt (n) 的一半足够了
ll n;
bool flag[MAX];
void pre (int x);
int main ()
{
//先分解质因子,然后计算奇因子的个数
scanf ("%lld",&n);
pre ((int)sqrt (n));//枚举到 sqrt(n)
int ans = 1;
for (int j = 1;j <= cnt && (ll)p[j] * p[j] <= n;++j)//边界枚举
{
int k = 0;
while (n % p[j] == 0)
{
if (j != 1) ++k;//第一个质数为 2
n /= p[j];
}
ans *= (k + 1);//算数基本定理
}
if (n > 2) ans *= 2;//注意剩余的那个质数也需要是奇数才行
printf ("%d\n",ans);
return 0;
}
void pre (int x)//线性筛质数
{
for (int i = 2;i <= x;++i)
{
if (!flag[i]) p[++cnt] = i;
for (int j = 1;j <= cnt;++j)
{
if (i * p[j] > x) break;
flag[i * p[j]] = 1;
if (i % p[j] == 0) break;
}
}
}