【CodeForces - 599D】Spongebob and Squares(推公式+枚举)

题意:

在一张3*5的网格图中,有15个1*1的矩阵,有8个2*2的矩阵,有3个3*3的矩阵,一共有26个不同的正方形。

现在已知一个矩形中包含一定数量的正方形,问这个矩形有多少种不同的可能。

Input

第一行包含一个整数 x (1 ≤ x ≤ 1018) — 表示矩形中包含的正方形个数。

Output

输出整数k表示有多少种不同的矩形满足条件

之后输出 k 对整数,每对整数描述一个矩形。按照 n 递增的顺序输出。

Example

Input

26

Output

6
1 26
2 9
3 5
5 3
9 2
26 1

Input

2

思路:

假设行数是k时,总共的格子数是m,我们的目标是找列的长度设为n(k<=n,因为k>n的时候其实在之前出现过)。首先只有一个格子的有k*n个,两个格子的有(k-1)*(n-1)个

三个格子的有(k-2)*(n-2)...把他们展开加和就能得到等式k*k*n-sum(k-1)(k+n)+sum2(k-1)=m,这里的sum(n)代表前n项的和,sum2(n)代表前n项的平方和。然后一化简就得到另一个数为(m-sum2(k-1)+sum(k-1)*k)/(k*k-sum(k-1))。代入k=1e6,m=1e18时测试,发现这时候k和n已经非常接近,所以直接暴力枚举就可以,然后用上面公式求出结果。

ac代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<vector>
#include<unordered_map>
#define mod (1000000007)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn=1e5+10;
struct node{
	ll l,r;
}ans[2000000];
ll sum(ll x){ return (x+1)*x/2; }
ll sum2(ll x){ return x*(x+1)*(x+x+1)/6; } 
int main(){
	ll m,k,cnt=0;
	scanf("%lld",&m);
	for(ll k=1;;k++){
		ll t1=(m-sum2(k-1)+sum(k-1)*k);
		ll t2=(k*k-sum(k-1));
		ll tmp=t1/t2;
		if(tmp<k) break;
		if(tmp*t2==t1){
			ans[cnt].l=k;ans[cnt++].r=tmp;
		}
	}
	printf("%d\n",cnt*2-(ans[cnt-1].l==ans[cnt-1].r));
	for(int i=0;i<cnt;i++){
		printf("%lld %lld\n",ans[i].l,ans[i].r);
	}
	if(ans[cnt-1].l!=ans[cnt-1].r) printf("%lld %lld\n",ans[cnt-1].r,ans[cnt-1].l);
	for(int i=cnt-2;i>=0;i--)
		printf("%lld %lld\n",ans[i].r,ans[i].l);
	return 0;
}
//k
//k*k*n-sum(k-1)(k+n)+sum2(k-1)=m
//tmp=(m-sum2(k-1)+sum(k-1)*k)/(k*k-sum(k-1))另一个数
//
//k*n (k-1)*(n-1) (k-2)(n-2)
//k*n kn-k-n+1   kn-2k-2n+4
//1 n
//2 2*n+1
//3 4n-4

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章