51nod1185威佐夫博弈+大數乘法模擬
阿新 • • 發佈:2018-12-01
題目就是正常的威佐夫博弈 關於威佐夫博弈三大博弈詳解
但是範圍是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;
}