4 条题解
-
1
这是一篇劝退版的题解。
$$\begin{aligned} \frac{1}{x}+\frac{1}{y}=\frac{1}{n!} \text{的正整数解的个数} &= \sum_{x \in N^*} \sum_{y \in N^*} [\frac{1}{x}+\frac{1}{y}=\frac{1}{n!}] \\ &= \sum_{x \in N^*} \sum_{y \in N^*} [\frac{xy}{x+y}=n!] \\ &= \sum_{x \in N^*} \sum_{y \in N^*} [xy=n!x+n!y] \\ &= \sum_{x \in N^*} \sum_{y \in N^*} [xy-n!y=n!x] \\ &= \sum_{x \in N^*} \sum_{y \in N^*} [y(x-n!)=n!x] \\ &= \sum_{x \in N^*} \sum_{y \in N^*} [y=\frac{n!x}{x-n!}] \\ &= \sum_{x \in N^*} [\frac{n!x}{x-n!} \in N^*] \\ &= \sum_{n!+1} ^{(n!)^2+n!} [\frac{n!x}{x-n!} \in N^*] \ \ \ \ \text{这一步跳了若干步确定上下界的步骤} \\ &= \sum_{1} ^{(n!)^2} [\frac{(n!)^2 + k \times n!}{k} \in N^*] \ \ \ \ \ \text{换元,令} k=x-n! \\ &= \sum_{1} ^{(n!)^2} [k \mid ((n!)^2 + k \times n!)] \\ &= \sum_{1} ^{(n!)^2} [k \mid (n!)^2] \\ &= \operatorname{d}((n!)^2) \text{注:}\operatorname{d}(n) \text{为 n 的约数个数} \end{aligned} $$ -
0
#include<bits/stdc++.h> using namespace std; int n; int prime[1000006],pct; bitset<1000006> not_prime; void euler(){ for(int i=2;i<=n;i++){ if(!not_prime[i]){ prime[++pct]=i; } for(int j=1;j<=pct&&prime[j]*i<=n;j++){ not_prime[i*prime[j]]=1; if(!(i%prime[j])) break; } } } const int P=1e9+7; long long ans=1; void find(){ for(int j=1;j<=pct;j++){ long long p=prime[j],ct=0; while(p<=n){ ct+=n/p;p=p*prime[j]; }ans=ans*(ct*2+1)%P; } } int main() { scanf("%d",&n); euler(); find(); printf("%lld",ans); return 0; } /* 1/x + 1/y = 1/n! 1/y = 1/n! - 1/x y = xn! / (x-n!) 若要让y为正整数, 需要: xn!和x-n!正整数 x-n! | xn! 设x-n! = k 则k|(k+n!)n!=kn!+n!*n! 因为k|kn!所以上式-> k|n!*n! 怎么求n!*n!的因数个数呢? 我们发现n!是由质数组成的 (这里先求n!的因数个数 只需要找到质数p在1~n中作为因数出现了多少次 (设为ct[p]次吧 cnt=连乘(ct[p_i]+1) //可以选p^0 ~ p^ct 那么对于n!*n!,只需让ct[p]*2即可 好的,那怎么找ct呢 在1~n中,ct[p] = n/p + n/p^2 +... (n/p记录了第一个p,n/p^2记录了第二个p...... OK*/ -
0
首先我们去分母:
然后我们考虑用 表示 ,则有:
然后我们上下同时除以 :
我们设 ,则有:
因为 一定为正整数,所以我们如果想要保证 为正整数,那么一定要保证 与 为正整数
但是注意此时 ,所以我们设
然后我们就会发现: 与 都必须为整数,那么 都一定是 的因数
这里注意每一个因数会被算两次即可
#include<iostream> #include<cstdio> #define int long long using namespace std; bool Test_MLE_start; const int N=1e6+10,mod=1e9+7; int T=1,cnt=0,n,ans=1; bool vis[N]; int prime[N],ret[N]; inline int reads(){ char c=getchar(); int sum=0,f=1; while(!isdigit(c)){ if(c=='-') f=-1; c=getchar(); } while(isdigit(c)){ sum=(sum<<3)+(sum<<1)+(c^'0'); c=getchar(); } return sum*f; } inline void files(){ freopen("std.in","r",stdin); freopen("std.out","w",stdout); } inline void clr(){ // Don't forget! } void ola(int p){ for(int i=2;i<=p;i++){ if(!vis[i]) prime[++cnt]=i; for(int j=1;j<=cnt&&prime[j]*i<=p;j++){ vis[prime[j]*i]=1; if(i%prime[j]==0) break; } } } bool Test_MLE_end; signed main(){ // printf("%lf Mb\n",(&Test_MLE_end-&Test_MLE_start-1)/1024.0/1024.0); // files(); // T=reads(); while(T--){ clr(),ola(N-10); n=reads(); for(int i=1;i<=cnt;i++){ if(prime[i]>n) break; for(int j=prime[i];j<=n;j*=prime[i]){ // cout<<i<<"->"<<prime[i]<<"->"<<j<<"\n"; ret[i]+=n/j; } ret[i]*=2; } ans=ret[1]+1; for(int i=2;i<=cnt;i++){ if(prime[i]>n) break; ans=ans*(ret[i]+1)%mod; } printf("%lld\n",ans); } return 0; } -
-2
原式可变为
然后很
不容易发现这个和因式分解很像所以我们两边同时加
然后这个东西等于
所以和是的约数
所以原问题就等价于求的约数个数,然后这个东西蓝皮书有讲
时间复杂度
code
#include <bits/stdc++.h> using namespace std; bool mlest; inline long long R(){ long long x = 0, f = 1; char ch = getchar(); while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar(); } while(isdigit(ch)) { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); } return x * f; } inline void W(long long x){ if(x < 0) { putchar('-'); x = -x; } if(x > 9) W(x/10); putchar(x%10+'0'); } inline void W(string s){ for(long long i = 0;i < s.size(); i++){ putchar(s[i]); } } inline void W(long long x,string s){ W(x); W(s); } long long n; void read(){ n = R(); } void init(){ } const long long N = 1e6 + 10; const long long mod = 1e9 + 7; bool vis[N]; long long p[N], tot, ans = 1; void compute(){ for(long long i = 2;i <= n; i++){ if(!vis[i]) { p[++tot] = i; long long num = 0; for(long long w = i;w <= n; w *= i){ num += n / w; num %= mod; } ans = ans * (num * 2 + 1); ans %= mod; } for(long long j = 1;j <= tot && p[j] * i <= n; j++){ vis[p[j] * i] = 1; if(i % p[j] == 0) break; } } W(ans); } bool mleed; int main(){ cerr << (&mleed-&mlest-1)/1024.0/1024.0 << "MB\n"; read(); init(); compute(); return 0; }
- 1
信息
- ID
- 208
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- (无)
- 递交数
- 25
- 已通过
- 15
- 上传者