1. 程式人生 > >51nod1185威佐夫博弈+大數乘法模擬

51nod1185威佐夫博弈+大數乘法模擬

題目就是正常的威佐夫博弈         關於威佐夫博弈三大博弈詳解

但是範圍是1e18  因為威佐夫博弈需要乘以黃金分割數1.618.......  所以在乘的時候會損失精度

需要模擬下大數乘法         關於大數乘法模擬大數乘法原理及實現

這裡再簡單說一下  如何模擬的乘法  模擬小學生豎式運算

舉個例子   三位數   123 乘以兩位數  45

    百位 十位 各位
    1 2 3
    4 5
——————————————————————————————————
    6(5+1) 1(10+1進1) 5(15進1)
  4 9(8+1) 2(進1)  
ans 5 5 3 5

這個大家都會  等於 5535

那麼  抽象一下

                 a0           a1           a2          三位數

                                t2            t1           兩位數

---------------------------------------------------

               t1*a0       t1*a1       t1*a2

 t2*a0      t2*a1       t2*a2                  

——————————————————進位累加得到答案

那麼我們也是這樣模擬  將1.618先不管1  只看後邊的小數

ll a[3]={618033988,749894848,204586834};//分成三部分  每部分是1e9

然後把 k 分成兩部分

ll t1=k%mod;//後半部分
ll t2=k/mod;//前半部分    都是1e9大小

然後按照剛才列的豎式進行計算  注意進位   就ok了 

ll ans=t1*a[2];             //可以看作三位數乘兩位數得到的結果的個位
ans=t1*a[1]+t2*a[2]+ans/mod;//十位
ans=t1*a[0]+t2*a[1]+ans/mod;//百位
ans=t2*a[0]+ans/mod;        //千位

ans+=k;//注意剛開始 忽略了1.618的1  現在要加上k  也就是算上那個1

ac程式碼

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1e4+7;
typedef long long ll;
//0.6180339887 4989484820 4586834365
ll a[3]={618033988,749894848,204586834};
ll mod=1e9;
int T;
ll A,B;
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld",&A,&B);
        ll x=min(A,B);
        ll y=max(A,B);
        ll k=y-x;

        // k*黃金比例
        ll t1=k%mod;
        ll t2=k/mod;
        ll ans=t1*a[2];
        ans=t1*a[1]+t2*a[2]+ans/mod;
        ans=t1*a[0]+t2*a[1]+ans/mod;
        ans=t2*a[0]+ans/mod;
        ans+=k;
        if(ans==x) printf("B\n");
        else printf("A\n");
    }
    return 0;
}