题意:求大于b的a的因数对有几组。例10 2结果为{2,5},12 2结果为{2,6}{3,4}-----不反复
解一:分解质因数+DFS
#include <iostream> #include <string.h> #include <math.h> using namespace std; typedef long long ll; const int maxn=1000005; int prime[maxn]; int num[maxn]; int dig[200]; int dignum[200]; int p; void inti() //筛选素数 { p=0; memset(prime,0,sizeof(prime)); memset(num,0,sizeof(num)); for(int i=2;i<maxn;i++) { if(!prime[i]) { num[p++]=i; for(int j=2;j*i<maxn;j++) prime[i*j]=1; } } return ; } ll pp; void dfs(ll tot,int t,int l,ll a,ll b) //dfs找到全部符合的因数 { if(((double)tot*tot)>=a) return ; if(tot>=b) pp++; for(int i=t;i<l;i++) { if(dig[i]) { ll temp=tot*dignum[i]; if(((double)temp*temp)>=a) return ; dig[i]--; dfs(temp,i,l,a,b); dig[i]++; } } return ; } int main() { ll a,b; int t; inti(); while(cin>>t) { for(int i=1;i<=t;i++) { pp=0; cin>>a>>b; double limit=sqrt(a*1.0); if(b>=limit) { cout<<"Case "<<i<<": 0"<<endl; continue; } ll temp=a; int j=0; int time=0; while(j<=p) //全部的质因数 { if((ll)num[j]*num[j]>temp) //小小的剪枝 break; int flag=0; while(!(temp%num[j])) { temp/=num[j]; flag++; } if(flag) { dignum[time]=num[j]; dig[time++]=flag; } j++; } if(temp!=1) { dignum[time]=temp; dig[time++]=1; } /*for(j=0;j<time;j++) cout<<dignum[j]<<" "<<dig[j]<<endl;*/ dfs(1,0,time,a,b); cout<<"Case "<<i<<": "<<pp<<endl; } } return 0; }
解二:直接计算
#include <iostream> #include <string.h> #include <math.h> using namespace std; typedef long long ll; const int maxn=1000005; int prime[maxn]; int num[maxn]; int dig[200]; int dignum[200]; int p; void inti() //找素数 { p=0; memset(prime,0,sizeof(prime)); memset(num,0,sizeof(num)); for(int i=2;i<maxn;i++) { if(!prime[i]) { num[p++]=i; for(int j=2;j*i<maxn;j++) prime[i*j]=1; } } return ; } /*ll pp; void dfs(ll tot,int t,int l,ll a,ll b) { if(((double)tot*tot)>=a) return ; if(tot>=b) pp++; for(int i=t;i<l;i++) { if(dig[i]) { ll temp=tot*dignum[i]; if(((double)temp*temp)>=a) return ; dig[i]--; dfs(temp,i,l,a,b); dig[i]++; } } return ; }*/ int main() { ll a,b; int t; inti(); ll sum; while(cin>>t) { for(int i=1;i<=t;i++) { sum=1; cin>>a>>b; if(((double)b*b)>=a) { cout<<"Case "<<i<<": 0"<<endl; continue; } ll temp=a; int j=0; int time=0; while(j<=p) { if((double)num[j]*num[j]>temp) break; int flag=0; while(!(temp%num[j])) { temp/=num[j]; flag++; } sum*=(flag+1); //排列组合。把全部的情况拿出来 j++; } if(temp!=1) { sum*=2; //还有没除尽的要给全部可能性乘2 } sum/=2; //直接除2,把反复的部分和正方形除去了 ll limit=sqrt(a*1.0); for(j=1;j<b;j++) //去掉不符合要求的矩形 if(!(a%j)) sum--; /*for(j=0;j<time;j++) cout<<dignum[j]<<" "<<dig[j]<<endl;*/ //dfs(1,0,time,a,b); cout<<"Case "<<i<<": "<<sum<<endl; } } return 0; }
第一种方法easy爆站。另外一种方法算是凑着它数据的b偏小才这么做的,两种方法个人感觉差点儿相同,希望各位大牛指正。