4 条题解

  • 1
    @ 2026-5-26 9:21:54

    这是一篇劝退版的题解。

    $$\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
      @ 2026-5-26 10:23:45
      #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
        @ 2025-5-9 17:01:23

        首先我们去分母:

        yn!+xn!=xyyn!+xn!=xy

        然后我们考虑用 yy 表示 xx,则有:

        y=xn!xn!y=\frac{xn!}{x-n!}

        然后我们上下同时除以 n!n!

        y=xxn!1y=\frac{x}{\frac{x}{n!}-1}

        我们设 m=xn!1m=\frac{x}{n!}-1 ,则有:

        x=(m+1)n!=mn!+n!x=(m+1)n!=mn!+n! y=mn!+n!m=n!+n!my=\frac{mn!+n!}{m}=n!+\frac{n!}{m}

        因为 n!n! 一定为正整数,所以我们如果想要保证 x,yx,y 为正整数,那么一定要保证 mn!mn!n!m\frac{n!}{m} 为正整数

        但是注意此时 mRm\in R ,所以我们设 m=ab  (b0)m=\frac{a}{b}~~(b≠0)

        然后我们就会发现:n!×abn! \times \frac{a}{b}n!×ban! \times \frac{b}{a} 都必须为整数,那么 a,ba,b 都一定是 n!n! 的因数

        这里注意每一个因数会被算两次即可

        #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
          @ 2025-5-9 10:34:57

          原式可变为

          xn!+yn!xy=0xn! + yn! - xy = 0

          然后很容易发现这个和因式分解很像

          所以我们两边同时加n!2n!^2

          n!2+xn!+yn!xy=n!2n!^2 + xn! + yn! - xy = n!^2

          LSH=(n!x)(yn!)LSH=(n!-x)(y-n!)

          然后这个东西等于n!2n!^2

          所以(n!x)(n!-x)(yn!)(y-n!)n!2n!^2的约数

          所以原问题就等价于求n!2n!^2的约数个数,然后这个东西蓝皮书有讲

          时间复杂度O(N)O(N)

          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
          上传者