Codechef:Short/SHORT
阿新 • • 發佈:2018-11-01
題解:
挺套路的。
設 ,則 。
然後列舉最小值 , ,在 較小的時候列舉 的約數,在 較大時,有: 。實踐證明,跑得飛快。
#include <bits/stdc++.h>
using namespace std;
typedef __int128 IL;
typedef long long LL;
inline void W(IL ans) {
static int buf[233];
if(!ans) {puts("0"); return;}
while(ans) buf[++buf[0]]=ans%10, ans/=10;
while(buf[0]) putchar(buf[buf[0]--]+'0'); puts("");
}
const int L=400000;
int pr[L+50],mnpr[L+50],pt;
inline void init() {
mnpr[1]=L+1;
for(int i=2;i<=L;i++) {
if(!mnpr[i]) mnpr[i]=pr[++pt]=i;
for(int j=1;j<=pt;j++) {
LL k=(LL)i*pr[j];
if(k>L) break;
mnpr[k]=pr[j];
if(!(i%pr[j])) break;
}
}
}
const int LIM=6000;
LL n,K,ans;
inline void solve() {
cin>>n>>K; ans=0;
if(!n) {W((IL)(K-1)*(K-1)); return;} K--;
for(LL a=n+1;a<=3.43*n && a<=K;a++) {
if(a>n+LIM) {
LL lim=(a*a-n)/((a-n)*(a-n)), p=a*n-n;
for(LL k=a/(a-n)+1;k<=lim;k++) {
LL b=n+p/(k*a-k*n-a);
if(b<=K && !((a*b-n)%((a-n)*(b-n)))) ans+=(a!=b)+1;
}
} else {
LL p1=a-1, p2=n;
static LL div[L],dc; div[dc=1]=1;
while(p1>1 || p2>1) {
LL t=min(mnpr[p1],mnpr[p2]), c=0;
while(mnpr[p1]==t) p1/=t, ++c;
while(mnpr[p2]==t) p2/=t, ++c;
for(int i=dc;i;i--)
for(LL j=1,v=1;j<=c;j++) div[++dc]=div[i]*(v*=t);
}
LL ori=(a-1)*n;
for(int i=1;i<=dc;i++) {
LL b=ori/div[i]+a;
if(n+div[i]<=K && !(b%(a-n)))
if(n+div[i]>=a) ans+=(n+div[i]!=a)+1;
}
}
} W(ans);
}
int main() {
init(); int T; cin>>T;
while(T--) solve();
}