(P1445)[バイオレット]桜(素因数分解)

トピックリンク:[バイオレット]桜-羅宮

分析:元の方程式の両辺にx * y *(n!)を掛けて、n!(x + y)= x * yを取得し、両辺に(n!)^ 2を加算して、n!(x + y )(n!)^ 2 =(n!)^ 2-n!(x + y)+ x * yを取得するには、方程式の右辺を注意深く観察し、(n!-x)に等しいことを確認します。 *(n!-y)の場合、方程式は次のように変換されます。

(n!-x)*(n!-y)=(n!)^ 2
問題は、正の整数解を見つけることです。x<= n!xとyは正の数なので、n!> (n!-x)> = 0、次にn!>(n!-y)> = 0、明らかに解決策はありません。n!未満の2つの数値の積は、(n!)^2より大きくすることはできません。したがって、xとyは両方ともnより大きいです!

つまり、(xn!)*(yn!)=(n!)^ 2

この方程式を使用すると、(xn!)と(yn!)がそれぞれ(n!)^ 2の2つの因子であることがわかり、xとyの整数解を求めると(n!)^2が求められます。因子の数、因子の数を見つける方法を知らない友人はここで見ることができます:因子の数と因子の合計

2からnまでの各数値に含まれる素因数とその累乗を直接見つけることができます。最後に、n ^ 2に含まれる素因数とその累乗を取得するには、累乗に2を掛けるだけです。

コードは次のとおりです。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
const int N=1e6+10,mod=1e9+7;
int prime[N],cnt,ans[N];
bool vis[N];
void init()
{
	for(int i=2;i<N;i++)
	{
		if(!vis[i]) prime[++cnt]=i;
		for(int j=1;j<=cnt&&i*prime[j]<N;j++)
		{
			vis[i*prime[j]]=true;
			if(i%prime[j]==0) break;
		}
	}
}
int main()
{
	int n;
	init();
	cin>>n;
//	for(int i=1;i<=cnt;i++) printf("%d\n",prime[i]);
	for(int i=2;i<=n;i++)
	{
		int t=i;
		for(int j=1;prime[j]*prime[j]<=i;j++)
			while(t%prime[j]==0)
			{
				ans[j]+=1;
				t/=prime[j];
			}
		if(t!=1)
			ans[(lower_bound(prime+1,prime+cnt+1,t)-prime)]++;//找到t对应的素数下标并将答案计入 
	}
	long long sum=1;
	for(int i=1;i<=cnt;i++)
		if(ans[i])
		sum=sum*(ans[i]*2+1)%mod;
	cout<<sum;
	return 0;
}

おすすめ

転載: blog.csdn.net/AC__dream/article/details/123914286