看到这道题,原以为是暴力枚举,一看题目难度和数据范围就明白了,这是道数学题(其实我是看标签知道的)。
好了,言归正传。
solution
- 首先,区间长度等于 1 是不可能的,具体可以看这篇题解。
- 当区间长度为 2 时,由于相邻的两个数互质,所以左端点 x 满足 x(x+1)=m 此时化简方程得 x2+x−m=0 用二次方程求根公式取较大的 2a−b+b2−4ac 得 x=2−1+1+4m 此时判断是否为整数即可。
- 当区间长度大于 2 时,我可以暴力枚举左端点和右端点预处理存在 map 中。
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| #include<iostream> #include<map> #include<cmath> using namespace std; typedef unsigned long long ll; map<ll,pair<ll,ll> > s; const ll INF=1e18; ll pgcd(ll x,ll y){ if(!y){ return x; } return pgcd(y,x%y); } inline void pdy(ll m){ ll x=sqrt(1+4*m); if(x*x==1+4*m){ x--; if(!(x&1)){ s[m]=make_pair(x/2,x/2+1); } } return; } int main(){ cin.tie(nullptr); ios::sync_with_stdio(false); ll z; cin>>z; for(ll i=1;i<=2000000;i++){ ll ans=i*(i+1); for(ll j=i+2;;j++){ ans/=pgcd(ans,j); if(ans>INF/j){ break; } ans*=j; if(!s.count(ans)){ s[ans]=make_pair(i,j); } } } while(z--){ ll m; cin>>m; if(s.count(m)){ cout<<s[m].first<<" "<<s[m].second<<"\n"; }else{ pdy(m); if(s.count(m)){ cout<<s[m].first<<" "<<s[m].second<<"\n"; }else{ cout<<"NIE\n"; } } } cout<<flush; return 0; }
|