一本通1624樱花
1624:樱花
时间限制: 1000 ms 内存限制: 524288 KB【题目描述】
原题来自: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;
对于全部数据,1≤n≤106 。
sol:好一道坑人的普及题,表示我就是被坑爆的蒟蒻
随便拆一下式子可得
原式:1/x + 1/y = 1/n!
--> (x+y) / (x*y) = 1/n!
--> (x+y)*n! = x*y
--> x*n!+y*n! = x*y
--> x*y-x*n! = y*n!
--> x*(y-n!) = y*n!
--> x = (y*n!) / (y-n!)
易知 x>n!, y>n! 令y=n!+T
--> x = (n!+T)*n! / T
--> x = (n!*n!) / T + n!
就是求(n!*n!)的约数个数
然后我就暴力分解质因数,TLE。。。TLE。。。TLE。。。
/* 原式:1/x + 1/y = 1/n! --> (x+y) / (x*y) = 1/n! --> (x+y)*n! = x*y --> x*n!+y*n! = x*y --> x*y-x*n! = y*n! --> x*(y-n!) = y*n! --> x = (y*n!) / (y-n!) 易知 x>n!, y>n! 令y=n!+T --> x = (n!+T)*n! / T --> x = (n!*n!) / T + n! 就是求(n!*n!)的约数个数 */ #include <bits/stdc++.h> using namespace std; typedef long long ll; inline ll read() { ll s=0; bool f=0; char ch=' '; while(!isdigit(ch)) { f|=(ch=='-'); ch=getchar(); } while(isdigit(ch)) { s=(s<<3)+(s<<1)+(ch^48); ch=getchar(); } return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<0) { putchar('-'); x=-x; } if(x<10) { putchar(x+'0'); return; } write(x/10); putchar((x%10)+'0'); return; } #define W(x) write(x),putchar(' ') #define Wl(x) write(x),putchar('\n') const int Mod=1000000007; const int N=1000005; int n; bool Bo[N]; int Prim[N],Pos[N]; ll Ges[N]; inline void Get_Prime() { int i,j; for(i=2;i<=n;i++) { if(!Bo[i]) { Prim[++*Prim]=i; Pos[i]=*Prim; } for(j=1;j<=*Prim&&Prim[j]*i<=n;j++) { Bo[Prim[j]*i]=1; if(i%Prim[j]==0) break; } } } int main() { int i,j; R(n); Get_Prime(); for(i=2;i<=n;i++) { int oo=i; for(j=2;j<=sqrt(oo);j++) if(oo%j==0) { while(!(oo%j)) { Ges[Pos[j]]++; oo/=j; } } if(oo>1) Ges[Pos[oo]]++; } for(i=1;i<=*Prim&&Prim[i]<=n;i++) { (Ges[i]<<=1)%=Mod; } ll ans=1; for(i=1;i<=*Prim&&Prim[i]<=n;i++) { ans=ans*(Ges[i]+1)%Mod; } Wl(ans); return 0; } /* input 2 output 3 input 5 output 63 input 999998 output 501065738 */
然后发现可以这样统计个数
for(i=1;i<=*Prim;i++) { for(j=Prim[i];j<=n;j*=Prim[i]) { Ges[i]+=1ll*n/j; } Ges[i]=(Ges[i]<<1)%Mod; }
为我的智障默哀。。。
/* 原式:1/x + 1/y = 1/n! --> (x+y) / (x*y) = 1/n! --> (x+y)*n! = x*y --> x*n!+y*n! = x*y --> x*y-x*n! = y*n! --> x*(y-n!) = y*n! --> x = (y*n!) / (y-n!) 易知 x>n!, y>n! 令y=n!+T --> x = (n!+T)*n! / T --> x = (n!*n!) / T + n! 就是求(n!*n!)的约数个数 */ #include <bits/stdc++.h> using namespace std; typedef long long ll; inline ll read() { ll s=0; bool f=0; char ch=' '; while(!isdigit(ch)) { f|=(ch=='-'); ch=getchar(); } while(isdigit(ch)) { s=(s<<3)+(s<<1)+(ch^48); ch=getchar(); } return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<0) { putchar('-'); x=-x; } if(x<10) { putchar(x+'0'); return; } write(x/10); putchar((x%10)+'0'); return; } #define W(x) write(x),putchar(' ') #define Wl(x) write(x),putchar('\n') const int Mod=1000000007; const int N=1000005; ll n; bool Bo[N]; int Prim[N],Pos[N]; ll Ges[N]; inline void Get_Prime() { int i,j; for(i=2;i<=n;i++) { if(!Bo[i]) { Prim[++*Prim]=i; Pos[i]=*Prim; } for(j=1;j<=*Prim&&Prim[j]*i<=n;j++) { Bo[Prim[j]*i]=1; if(i%Prim[j]==0) break; } } } int main() { ll i,j; R(n); Get_Prime(); for(i=1;i<=*Prim;i++) { for(j=Prim[i];j<=n;j*=Prim[i]) { Ges[i]+=1ll*n/j; } Ges[i]=(Ges[i]<<1)%Mod; } ll ans=1; for(i=1;i<=*Prim&&Prim[i]<=n;i++) { ans=ans*(Ges[i]+1)%Mod; } Wl(ans%Mod); return 0; } /* input 2 output 3 input 5 output 63 input 999998 output 501065738 */
河田は河田、赤木は赤木……。
私は誰ですか。教えてください、私は誰ですか。
そうだ、俺はあきらめない男、三井寿だ!