2013-06-05 110 views
2

我發現一個很好的數學問題,但我仍然無法解決它,我試圖找到一個解決方案,使用谷歌,發現它可以解決使用二進制索引樹數據結構,但解決方案並不清楚。如何使用BIT解決此問題?

這裏稱爲查找魔術三胞胎的問題,它可以在UVA線上解題系統中找到:

(A + B^2)模k = C^3模k,其中一個< = B < = c和1 < = a,b,c < = n。

給定n和k(1 < = n,k < = 10^5),對於已知的n和k值存在多少個不同的魔術三元組。如果三個值中的任何一個在三個中都不相同,則三元組與另一個不同。

,並在這裏,我找到了解決辦法:

#include <cstdio> 
#include <cstring> 
using namespace std; 

typedef long long int64; 

const int MAX_K = (int)(1e5); 

int N, K; 

struct BinaryIndexedTree{ 

    typedef int64 bit_t; 

    static const int MAX_BIT = 3*MAX_K + 1; 
    bit_t data[MAX_BIT+1]; 
    int SIZE; 

    void init(int size){ 
     memset(data, 0, sizeof(data)); 
     SIZE = size; 
    } 

    bit_t sum(int n){ 
     bit_t ret = 0; 
     for(;n;n-=n&-n){ 
      ret += data[n]; 
     } 
     return ret; 
    } 

    bit_t sum(int from, int to){ 
     return sum(to)-sum(from); 
    } 

    void add(int n, bit_t x){ 
     for(n++;n<=SIZE;n+=n&-n){ 
      data[n]+=x; 
     } 
    } 
}; 

BinaryIndexedTree bitree; 


void init(){ 
    scanf("%d%d", &N, &K); 
} 

int64 solve(){ 
    bitree.init(2*K+1); 

    int64 ans = 0; 
    for(int64 i=N; i>=1; i--){ 
     int64 b = i * i % K, c = i * i * i % K; 
     bitree.add(c, 1); 
     bitree.add(c+K, 1); 
     bitree.add(c+2*K, 1); 
     int64 len = i; 
     if(len >= K){ 
      ans += (len/K) * bitree.sum(K); 
      len %= K; 
     } 
     if(len > 0){ 
      ans += bitree.sum(b + 1, b + len + 1); 
     } 
    } 

    return ans; 
} 

int main(){ 
    int T; 
    scanf("%d", &T); 
    for(int i=0; i<T; i++){ 
     init(); 
     printf("Case %d: %lld\n", i+1, solve()); 
    } 

    return 0; 
} 
+0

您可以添加一些測試用例,以便可以驗證任何解決方案嗎? –

+0

@MarkusJarderot [鏈接] http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3860有問題的鏈接,例子是n = 10和k = 7有27個不同的三胞胎。 – user2456277

+0

那麼你想了解這個解決方案,還是不行?它不太清楚你的實際問題是什麼。 –

回答

1

你決心使用BITS?我會認爲普通的數組會這樣做。我首先創建三個大小爲k的數組,其中arrayA [i] =範圍內的值的數量等於i mod k,arrayB [i] =在範圍中的b值的數量,其中b^2 = i mod k和arrayC [i] = c的值的數量,其中c^3 = i mod k。 N和k都是< = 10^5,所以您可以依次考慮a的每個值,反過來依次考慮c,然後依次考慮c,但如果k比n小得多,則可以更清楚,因爲它們會是某種fiddly fence-post counting表達式,允許你計算0..n範圍內有多少數字等於每個i的i mod k。

給定那三個數組,然後考慮每個可能的數字對i,j,其中0 < = i,j < k並且計算出具有這些值mod k的arrayA [i] * arrayB [j]對。在arrayAB [i + j mod k]中求和這些以找出可以選擇a + b^2 mod k = x的方式的數量,其中0 < = x < k。現在你有兩個數組arrayAB和arrayC,其中arrayAB [i] * arrayC [i]是找到一個三元組的方法的數量,其中a + b^2 = c^3] = i,所以總和爲0 < =我< k得到你的答案。

+0

謝謝你的回覆,但是我必須說你的解決方案根本不正確,首先是因爲我猜你並沒有考慮到a <= b <= c的事實,其次是因爲它沒有效率如果我沒有錯的話,它的複雜度是O(K^2)。 – user2456277

+0

對於透視圖,BIT對'sum'和'add'都具有'log(n)'複雜度,所以OP的解決方案是'O(N * log(K))' –

+0

好吧,這個想法與此類似,算法開始將b從N設置爲1,因爲c應該大於b,所以當b是N時,c的唯一可能值也是N,那麼b是N-1並且c可以是N-1或N,N已經在BIT就足以設置c = N-1並將此值添加到BIT中,最後a的值的數量爲len/K,即整數除法提供每個餘數的數量。 – user2456277