HDU 5750 Dertouzos 简单数学
感悟:这又是zimpha巨出的一场题,然后04成功fst(也就是这题)
实际上还是too young,要努力增加姿势,
分析:直接枚举这些数不好枚举,换一个角度,枚举x*d,也就是d的另一个乘数是多少
显然 x<=min(d,(n-1)/d),x还得是质数,最后发现x必须小于d的最小因子
然后预处理10w以内的素数,然后每次先得到k=min(d,(n-1)/d),然后看d最小因子是否小于k
这题的关键就在找d的最小因子,我是暴力找的(然后碰上全是大素数就t了)
实际上当d是大素数的时候,k很小,直接枚举质数,如果大于k还没有,就不用再找了(反正去最小)
赛后加上这一个限制就过了
吐槽:还是年轻
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <vector> #include <math.h> #include <stack> #include <map> #define x first #define y second using namespace std; typedef long long LL; const int N = 1e5+5; const int INF = 0x3f3f3f3f; typedef pair<int,int>pii; bool vis[N]; int prime[N>>1],tot; void getprime(){ for(int i=2;i*i<=N-5;++i){ if(vis[i])continue; for(int j=i*i;j<=N-5;j+=i) vis[j]=true; } for(int i=2;i<=N-5;++i) if(!vis[i])prime[++tot]=i; } int main(){ getprime(); int T; scanf("%d",&T); while(T--){ int n,d; scanf("%d%d",&n,&d); int tmp=min(d,(n-1)/d); int flag=-1; for(int i=1;i<=tot&&prime[i]<=tmp&&1ll*prime[i]*prime[i]<=d;++i){ if(d%prime[i])continue; else {flag=prime[i];break;} } if(flag==-1)flag=d; tmp=min(tmp,flag); int k=lower_bound(prime+1,prime+1+tot,tmp)-prime; if(k==tot+1||prime[k]>tmp)--k; printf("%d\n",k); } return 0; }