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

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 100005
using 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;
}
發佈了77 篇原創文章 · 獲贊 22 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章