XJOI 3393 序列 題解

時間:1s 空間:128M

題目描述:

f(0)=0
f(2∗x)=f(x)
f(2∗x+1)=f(x)+1
你有一個序列a1,a2,a3…an
現在你想知道有多少對的f(ai)=f(aj)(1<=i< j<=n)

輸入格式:

第一行輸入一個整數n
第二行輸入n個整數ai

輸出格式:

輸出一個整數

樣例輸入1:

3
1 2 4

樣例輸出1:

3

樣例輸入2:

3
5 3 1

樣例輸出2:

1

約定:

1<=n<=10^5,1<=ai<=10^9

提示:

首先,如何求f(x),可以用遞歸解決。時間複雜度較小,而且如果用記憶化,空間會開不下。求f(x)的代碼如下:

int mrz_key ( int k )
{
    if ( k == 0 ) return 0; 
    if ( k % 2 == 0 ) return mrz_key ( k / 2 ) ;
    if ( k % 2 == 1 ) return mrz_key ( k / 2 ) + 1 ;
}

其次,我們會發現,f(x)的值其實不是很大,甚至可以用桶來存儲。tonnn數組就是一個桶。我們不妨做一個假設,tonnn[i]=5,也就是說f(x)值是i的有5個,則可得相等的值有(4+3+2+1)對,就可以用等差數列求和公式來做。代碼如下:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std ;
int tonnn [ 1000000 ] , a [ 100001 ] , n ;
int mrz_key ( int k )
{
    if ( k == 0 ) return 0; 
    if ( k % 2 == 0 ) return mrz_key ( k / 2 ) ;
    if ( k % 2 == 1 ) return mrz_key ( k / 2 ) + 1 ;
}
int main ( )
{
    scanf ( "%d" , & n ) ;
    memset ( tonnn , 0 , sizeof ( tonnn ) ) ;
    int maxx = 0 , d ;
    tonnn [ 0 ] = 1 ;
    for ( int i = 1 ; i <= n ; i ++ )
    {
        scanf ( "%d" , & a [ i ] ) ;
        d = mrz_key ( a [ i ] ) ;
        if ( d > maxx ) maxx = d ;
        tonnn [ d ] ++ ;
    }
    int ans = 0 ;
    for ( int i = 1 ; i <= maxx ; i ++ ) 
        if ( tonnn [ i ] > 1 ) ans += ( tonnn [ i ] - 1 ) * tonnn [ i ] / 2 ;
    printf ( "%d" , ans ) ;
    return 0 ;
}

相關鏈接:

XJOI 題解小全:
https://blog.csdn.net/zj_mrz/article/details/80949787

XJOI 3265 Climb the stairs 爬樓梯 題解:
https://blog.csdn.net/zj_mrz/article/details/80970052

發佈了45 篇原創文章 · 獲贊 60 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章