http://www.yyycode.cn/index.php/2020/06/19/%e7%ba%aa%e5%bf%b5%e9%82%ae%e7%a5%a8/
Description
郵局最近推出一套郵票, 這套郵票共有n張,郵票面值各不相同,按編號順序爲1分,2分,3分...... 小航是一個集郵愛好者,他很喜歡這套郵票,可惜他現在身上只有M分,並不夠把全套都買下。他希望儘量買,最好剛好把所有的錢花光。作爲一個集郵愛好者,小航也不想買的編號斷斷續續。多義性小航打算買面值a分至b分的b-a+1張連續郵票,且總價剛好爲M 你的任務是求出所有符合條件的方案,以[a,b]的形式輸出。
Input
每個測試數據只有一行,包含兩個整數N,M(1 <= N, M <= 10^9)
Output
輸出所有的方案,按a重小到大輸出。 輸出文件不包含任何空格
Sample Input
20 15
Sample Output
[1,5] [4,6] [7,8] [15,15]
思路:看到1e9,O(n)的做法是肯定卡的。估計是往log(n)或者sqrt(n)轉化。最開始是枚舉begin的,那我們轉化一下枚舉區間有多少個數。設區間的多少個數爲i;
由等差公式可以推 (begin+end)*i/2=M–>(begin+end)*i==2M;到這一步繼續轉化,(2*begin+i-1)*i==2M;這裏就可以看出來枚舉的i的範圍在sqrt(2M)內,然後就可以把枚舉的範圍縮小了
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=1e5;
typedef long LL;
int main(void)
{
LL N,M,begin,end;
while(cin>>N>>M)
{
for(LL i=sqrt(2*M);i>=1;i--)//i->郵票張數
{
if(2*M%i==0&&((2*M/i)-i+1 )%2==0&&((2*M/i)-i+1)/2>=1&&((2*M/i)-i+1)/2+i-1<=N)
{
begin=((2*M/i)-i+1)/2;
end=((2*M/i)-i+1)/2+i-1;
cout<<"["<<begin<<","<<end<<"]"<<endl;
}
}
}
return 0;
}