题目描述
题意:求不定方程1x+1y=1n!的正整数解的个数.
(x,y为未知数,n为给定的数)
样例
输入样例: 1439
输出样例: 102426508
线性筛素数(主要算法:数学推导)
下面是玄学数学推导时间:
因为
1x+1y=1n!
可以很轻松地看出 1x和1y是小于1n!的,于是由小学知识可知x和y是大于n!的.
于是,我们令
y=n!+k (k\in \{N*})
于是,原式变为
1x+1n!+k=1n!
两边通分,得
n!×(n!+k)+x×n!=x×(n!+k)
整理,得
x=(n!)2k+n!
分析至此,已经比较明晰了.
因为x是正整数,则(n!)2k+n!也必须为正整数.
又因为{n!}\in\{N*},故只需(n!)2k为正整数即可.
由于k可以为任意正整数,故k只需取(n!)2的约数即可.
此时x=(n!)2k+n!为正整数,y=n!+k也为正整数,故这样的k是满足题意的.
所以本题的实质其实是:
求(n!)2的正约数个数和
玄学数学推导终于结束了…
接下来才是真正与算法有关的部分了.
我们知道,一个正整数可以被唯一分解为
N=pc11⋅pc22⋅pc33⋯pcmm
其中ci均为正整数,pi均为质数,且满足p1<p2<p3<⋯<pm
则N的正约数个数为
(c1+1)⋅(c2+1)⋅(c3+1)⋅⋯⋅(cm+1)=m∏i=1(ci+1)
所以我们只需找出所有的ci即可.
为了提高效率,我们采用线性筛素数的方法,先找出n!的质因子,再通过分解质因数的方法找出所有的ci即可.
注意我们这里只是找出了n!的所有的ci,而题目要求的是(n!)2的约数个数,所以统计时一定要乘2!!!!
因为平方过后,n!的所有ci都变为了2ci.(这个应该可以理解吧....)
还有一件事,记得取模(此事非常重要)!!!!
自此,你就完美的解决了这道题.
时间复杂度 O(nlogn)
C++ 代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll MAX=1e6+1;
const ll mod=1e9+7;
ll n,ans=1;
ll c[MAX],prime[MAX];//c[i]为指数
ll flag[MAX],s[MAX];
int tot;
inline void Linear()//线性筛素数 (查找1到n中每个数的最小质因子并记录位置)
{
for(int i=2;i<=n;i++){
if(!flag[i]){
prime[++tot]=i;
s[i]=tot;
}
for(int j=1;j<=tot&&i*prime[j]<=n;j++){
flag[i*prime[j]]=1;
s[i*prime[j]]=j;// s[i] 表示 i 的最小质因子在prime数组中的位置
if(i%prime[j]==0)
break;
}
}
}
inline void divide(int x)//将x分解质因数
{
while(x!=1){
++c[s[x]];//s[x]为x的最小质因子,c[s[x]]表示s[x]这个质因子的指数
x/=prime[s[x]];//分解
}
}
int main()
{
scanf("%lld",&n);
Linear();
for(int i=1;i<=n;i++)
divide(i);
for(int i=1;i<=MAX;i++)
if(c[i])
ans=ans*(2*c[i]+1)%mod;//注意这里要乘二,因为最后统计的是n!的约数个数,而不是n!,所以所有的ci要变为2*ci
printf("%lld\n",ans);
return 0;
}
/*
*
* ┏┓ ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃ ┃
* ┃ ━ ┃ ++ + + +
* ████━████+
* ◥██◤ ◥██◤ +
* ┃ ┻ ┃
* ┃ ┃ + +
* ┗━┓ ┏━┛
* ┃ ┃ + + + +Code is far away from
* ┃ ┃ + bug with the animal protecting
* ┃ ┗━━━┓ 神兽保佑,代码无bug
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛ + + + +
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛+ + + +
*/
唯一收获:可复制的神兽
orz
大佬,c数组开到MAX,下标是0~MAX-1,for(int i=1;i<=MAX;i++)中调用c[i]不会报错吗?
不开O2可能能过
奇奇怪怪的。。。
好
艹,好难。。。
我是数学垃圾。。
%
%
题解错了,应该是x=n!/k+n!
不影响答案
不好意思打错了。。已修改
#### 最后 神仙保佑啥子情况 hh
%%%
niu B plus
大佬,I lvoe you!!!
大佬,最后推出来的x不是应该加n!吗?为什么是k???
赞👍