传送门:Aladdin and the Flying Carpet
题意: 给出两个正整数1<=m<=n<=1e12。问N可以拆成多少对p*q,使得p和q中最小的不小于a,且p!=q。
分析:先log(n)求出n的总因子个数,然后再排除因子小于m的个数,若m*m>n答案必定为0,否则可以暴力1~m排除因子小于m的个数,这里稍微优化一下dfs排除小于m的因子个数。
#pragma comment(linker,"/STACK:1024000000,1024000000") #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <limits.h> #include <iostream> #include <algorithm> #include <queue> #include <cstdlib> #include <stack> #include <vector> #include <set> #include <map> #define LL long long #define mod 100000000 #define inf 0x3f3f3f3f #define eps 1e-6 #define N 1000000 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define PII pair<int,int> using namespace std; inline LL read() { char ch=getchar();LL x=0,f=1; while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch<=‘9‘&&ch>=‘0‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } int prime[N/10],tot; bool vis[N+5]; int ans; LL n,m; void init() { memset(vis,false,sizeof(vis)); for(int i=2;i<=N;i++) { if(!vis[i]) { prime[tot++]=i; } for(int j=0;j<tot&&i*prime[j]<=N;j++) { vis[i*prime[j]]=true; if(i%prime[j]==0)break; } } } void dfs(int dep,LL x) { ans--; for(int i=dep;i<tot;i++) { if(x*prime[i]<m) { if(n%(x*prime[i])==0) dfs(i,x*prime[i]); } else return; } } int main() { int T,cas=1; init(); T=read(); while(T--) { n=read();m=read();LL temp=n; printf("Case %d: ",cas++); if(m*m>=n) { puts("0");continue; } ans=1; for(int i=0;i<tot&&(LL)prime[i]*prime[i]<=temp;i++) { if(temp%prime[i]==0) { int x=0; while(temp%prime[i]==0) { x++;temp/=prime[i]; } ans*=(x+1); } } if(temp>1) { ans*=2; } ans/=2; if(m>1)dfs(0,1); printf("%d\n",ans); } }
原文:http://www.cnblogs.com/lienus/p/4299001.html