Codeforces Round #332 (Div. 2) D. Spongebob and Squares详解

来源:互联网 发布:工程软件工作量估计 编辑:程序博客网 时间:2024/06/10 22:03

D. Spongebob and Squares
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Spongebob is already tired trying to reason his weird actions and calculations, so he simply asked you to find all pairs of n and m, such that there are exactly x distinct squares in the table consisting of n rows and m columns. For example, in a 3 × 5 table there are 15 squares with side one, 8 squares with side two and 3 squares with side three. The total number of distinct squares in a 3 × 5 table is 15 + 8 + 3 = 26.
Input
The first line of the input contains a single integer x (1 ≤ x ≤ 1018) — the number of squares inside the tables Spongebob is interested in.
Output
First print a single integer k — the number of tables with exactly x distinct squares inside.
Then print k pairs of integers describing the tables. Print the pairs in the order of increasing n, and in case of equality — in the order of increasing m.
Sample test(s)
Input
26
Output
6
1 26
2 9
3 5
5 3
9 2
26 1
Input
2
Output
2
1 2
2 1
Input
8
Output
4
1 8
2 3
3 2
8 1

题意:给一个正方形个数sum。sum等于n*m的矩形内部正方形个数之和。求出所有数对(n,m)。

思路:
数据结构的选取:由于是数对,且要排序,结构体就满足。
算法的选取:求一个n*m矩形内部正方形之和,一定有个公式,重点是推出该公式。给定n*m矩形,经过找规律发现内部正方形个数之和sum=∑(k=1->n)〖[n-(k-1)][m-(k-1)]〗=n(n+1)/2+(n-n*n*n)/6,其中k表示内部正方形边长。由于n和m都是变量,所以枚举n,根据n和sum求m即可。
变式:m=(n*n*n-n+6*sum)/(3*n*(n-1))。为了减少运算量,令tmp1= n*n*n-n+6*sum,tmp2=3*n*(n-1)。当tmp1%tmp2==0时,找到一个m=tmp1/tmp2。
有一个问题,x高达10^18,n不能枚举那么大。由于矩形是对称的, 所以只需要求n<=m部分的n。所以枚举条件就是n<=m,即n小于tmp1/tmp2。
还有,这样的矩形(即数对(n,m))有多少个,需要多大的数组来存?由上面的公式发现,sum是关于n的三次函数,10^18开三次方,所以 估计100万,而很容易发现矩形数不会很多,所有先给10万的数组试一试。

此方法在所有方法中算很快的了,其余的大部分是500ms以上。

// 62 ms    1600 KB。#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#define maxn 100005using namespace std;struct Node{    long long n;    long long m;    Node(long long N=0, long long M=0){        n=N;m=M;    }}N[maxn];bool cmp(Node a,Node b){    return a.n==b.n?a.m<b.m:a.n<b.n;}int main(){    freopen("input.txt","r",stdin);    freopen("output.txt","w",stdout);    long long n,m,sum;    while(scanf("%I64d",&sum)==1){        if(sum==1){            cout<<1<<endl<<1<<" "<<1<<endl;        }        else{        int k=0;        N[k++]=Node(1,sum);        n=2;        long long tmp1=n*n*n-n+6*sum,tmp2=3*n*(n+1) ;        for(n=2;n<=tmp1/tmp2;){            if(tmp1%tmp2==0){                N[k++]=Node(n,tmp1/tmp2);            }            n++;            tmp1=n*n*n-n+6*sum,tmp2=3*n*(n+1);        }        int tmpk=k;        for(int i=0;i<tmpk;i++){           if(N[i].n!=N[i].m) N[k++]=Node(N[i].m,N[i].n);        }        sort(N,N+k,cmp);        cout<<k<<endl;        for(int i=0;i<k;i++){            cout<<N[i].n<<" "<<N[i].m<<endl;        }        }    }    return 0;}
0 0
原创粉丝点击