樱花(信息学奥赛一本通 1624)

【题目描述】

原题来自:HackerRank Equations

求不定方程: 1/x + 1/y = 1/n!

的正整数解 (x,y)的数目。

【输入】

一个整数 n

【输出】

一个整数,表示有多少对 (x,y) 满足题意。答案对 109+7 取模。

【输入样例】

2

【输出样例】

3

【提示】

样例说明

共有三个数对 (x,y) 满足条件,分别是 (3,6),(4,4) 和 (6,3)。

数据范围与提示:

对于 30% 的数据,n≤100;

对于全部数据,1n106 。


 

(这里不得不吐糟一下,书上把题目打错了啦,n!写成了n,害得我还以为这道题可以暴力去做,结果光荣的爆零了(▼⊿▼))

首先呢就是用数学方法把这个不定方程变化一下,令y=n+a(x、y肯定比n大啦,可以自己推导一下),很容易就得到了 x = (n!*n!) / a+ n!

那么因为n!为整数、x也为整数,所以(n!*n!) / a一定也为整数。那要求x的个数的话就是要求满足(n!*n!) / a为整数的a的个数

所以说这道题很快就转化成了一道求约数个数的题目。

然后就是唯一分解定理和约数个数定理...

上代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1e6+1,M=1e9+7;
 4 int a[N],n,v[N],cnt,b[N],num[N];//b[x]表示x的最小质因子是质数中的第几号 
 5 long long ans=1;
 6 int read()
 7 {
 8     int x=0,f=1;
 9     char ch=getchar();
10     while(ch<'0'||ch>'9')
11     {
12         if(ch=='-') f=-1;
13         ch=getchar();
14     }
15     while(ch>='0'&&ch<='9')
16     {
17         x=x*10+ch-'0';
18         ch=getchar();
19     }
20     return x*f;
21 }
22 void write(int x)
23 {
24     if(x<0)
25     {
26         putchar('-');
27         x=-x;
28     }
29     if(x>9) write(x/10);
30     putchar(x%10+'0');
31 }
32 void pre()
33 {
34     for(int i=2;i<=1000000;i++)
35     {
36         if(!v[i])a[++cnt]=i,b[i]=cnt;
37         for(int j=1;j<=cnt&&a[j]*i<=1000000;j++)
38         {
39             v[i*a[j]]=1;b[i*a[j]]=j; 
40             if(i%a[j]==0)break;
41         }
42     }
43 }
44 void ff(int x)
45 {
46     while(x!=1)
47     {
48         num[b[x]]++;//num[i]表示i这个序号代表的质因子出现的次数(也就是b[i]的幂的次数啦) 
49         x/=a[b[x]];//x不断更新 
50     }
51 }
52 int main()
53 {
54     
55     n=read();
56     pre();
57     for(int i=2;i<=n;i++)
58         ff(i);
59     for(int i=1;i<=cnt;i++)
60         ans=ans*(num[i]*2+1)%M;
61     printf("%lld",ans);
62     return 0;
63 }

//参考:这位大佬讲的hin好,点击%大佬的博客

转载于:https://www.cnblogs.com/ljy-endl/p/11378174.html

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值