OUPC2012 問題D Four Arithmetic Operations (AOJ2353)
制約条件
n≦10^5
-10^6≦yi≦10^6
最後の答えは-2^31以上2^31未満の整数になる
方針
最後の答えが-2^31以上2^31未満の整数になることが保証されているので、
適当に大きな素数pを選び、pを法とした余りで計算をすればよい。
pが大きいとp^2が2^64を超えて、long longをオーバーフローする可能性があるので、
JavaでBigIntegerを使うか、適当に素数を二つ選んで、それぞれで計算して中国剰余定理で合成するなどする。
ソースコード
ll extgcd(ll a,ll b,ll &x,ll &y){ ll g=a; x=1; y=0; if(b)g=extgcd(b,a%b,y,x), y-=a/b*x; return g; } ll inv(ll a,ll m){ ll x,y; extgcd(a,m,x,y); return (x%m+m)%m; } const int m1=999979,m2=999983; int main(){ int n,o,y; ll a=0,b=0; cin>>n; rep(i,n){ cin>>o>>y; if(o==1)a=(a+y)%m1, b=(b+y)%m2; if(o==2)a=(a-y%m1+m1)%m1, b=(b-y%m2+m2)%m2; if(o==3)a=(a*y)%m1, b=(b*y)%m2; if(o==4)a=(a*inv(y,m1))%m1, b=(b*inv(y,m2))%m2; } ll p,q; extgcd(m1,m2,p,q); ll ans=(b*m1*p+a*m2*q)%((ll)m1*m2); if(ans>=1ll<<31)ans-=(ll)m1*m2; cout<<ans<<endl; return 0; }