#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}
template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}
const int N=1e6,M=0,Z=1e9+7,ms63=1061109567;
int casenum,casei;
LL x;
//pair<LL,LL>a[N];int g;
set< pair<LL,LL> >sot;
int main()
{
//m=(2*(x-前(n-1)项的sqrsum))/n+n*(n-1))/(n+1)
while(~scanf("%llu",&x))
{
sot.clear();//g=0;
LL sqrsum=0;
for(LL n=1;;++n)
{
if(sqrsum>x)break;
LL tmp=(x-sqrsum)*2;
if(tmp%n==0)
{
tmp=tmp/n+n*(n-1);
if(tmp%(n+1)==0)
{
LL m=tmp/(n+1);
if(n<=m)
{
//a[++g]=MP(n,m);
//if(n!=m)a[++g]=MP(m,n);
sot.insert(MP(n,m));
sot.insert(MP(m,n));
}
}
}
sqrsum+=n*n;
}
printf("%d\n",sot.size());
for(set< pair<LL,LL> >::iterator it=sot.begin();it!=sot.end();++it)printf("%llu %llu\n",it->first,it->second);
//printf("%d\n",g);sort(a+1,a+g+1);
//for(int i=1;i<=g;++i)printf("%lld %lld\n",a[i].first,a[i].second);
}
return 0;
}
/*
【trick&&吐槽】
我们一开始定义n<=m,不代表求出来的就满足n<=m。
比如对x==2,n==2时,m=(2*(x-前(n-1)项的sqrsum))/n+n*(n-1))/(n+1)=1。
如果不是用set判重的话,我们需要判定n<=m这个条件。
【题意】
数学
【类型】
给你一个x,让你求出所有的矩形,使得该矩形内正方形的数量恰好为x。
矩形内正方形的数量这样定义——
假如说矩形的长为n*m,并使得n<=m,那么矩形内有——
1*1的正方形有n*m个
2*2的正方形有(n-1)*(m-1)个
3*3的正方形有(n-2)(m-2)个
n*n的正方形有(n-n+1)*(m-n+1)个
即:(n*m)+(n-1)*(m-1)+(n-2)*(m-2)+(n-3)*(m-3)+...+(n-n+1)*(m-n+1)的总和恰好为x
【分析】
做这种数学类的,公式推理性质比较强的题目,一定要保证自己的公式推理严谨认真不出错。
我们这题的公式为(n*m)+(n-1)*(m-1)+(n-2)*(m-2)+(n-3)*(m-3)+...+(n-n+1)*(m-n+1)==x。
这里的n为矩形长与宽的较小值,公式化简一下,变成了——n*n*m+1*1+2*2+3*3+...+(n-1)*(n-1)-(1+2+3+...+n-1)(n+m)==x。
而x^2的前n项和的公式是n(n+1)(2n+1)/6。所以n的上限也不过只有sqrt(6e18)级别。
于是我们暴力枚举n,然后得到n*n*m-(1+2+3+...+n-1)(n+m)==x-(1*1+2*2+3*3+...+(n-1)*(n-1))。
为了化简,我们把(1+2+3+...+n-1)写成公式的形式,即n*n*m-(n*(n-1))/2*(n+m)==x-(1*1+2*2+3*3+...+(n-1)*(n-1))
我们左右同时除以一个n,得到n*m-(n-1)(n+m)/2==(x-(1*1+2*2+3*3+...+(n-1)*(n-1)))/n
然后左边拆开,得到n*m-(n*n-n+n*m-m)/2==(x-(1*1+2*2+3*3+...+(n-1)*(n-1)))/n
发现两边还是同时乘以一个2的好,于是得到2*n*m-(n*n-n+n*m-m)==2*(x-(1*1+2*2+3*3+...+(n-1)*(n-1)))/n
再化简,得到2*n*m-n*n-n*m+n+m==2*(x-(1*1+2*2+3*3+...+(n-1)*(n-1)))/n
即(n+1)*m==2*(x-(1*1+2*2+3*3+...+(n-1)*(n-1)))/n+n*n-n
即m=(2*(x-(1*1+2*2+3*3+...+(n-1)*(n-1)))/n+n*(n-1))/(n+1)
于是我们就可以求得m,要求m>=n
【时间复杂度&&优化】
O(nlogn)
*/
【Codeforces Round 332 (Div 2)D】【数学 公式推导】Spongebob and Squares 正方形数量恰好为x个的所有大矩形
最新推荐文章于 2024-09-30 01:36:19 发布