アイデア勝負な問題。
https://yukicoder.me/problems/no/3278
問題
整数変数x=0がある。また、素数Pがあったとする。Pは明に与えられない。
xに以下のクエリを計N個順次適用することを考える。
- 各クエリは演算子と整数値A[i]を取る。演算子に応じて以下のいずれかを行う。
- xにA[i]を加算し、Pで割ったあまりに置き換える。
- xにA[i]を掛け、Pで割ったあまりに置き換える。
- xをA[i]で割り、Pで割ったあまりに置き換える。
この結果と同じ処理を、加算・乗算をN回までと、除算を1回まで使い表現するプログラムを構築せよ。
このプログラムでは、Aの各値に加え、26個の整数変数を使える。
解法
割り算を1回でまとめるため、x=p/qと有理数の形で持とう。
そうすれば
- xへのA[i]の加算は、p = (p + A[i]*q) % P とすればよい
- xへのA[i]の乗算は、p = p*A[i] % P とすればよい
- xへのA[i]の除算は、q = q*A[i] % P とすればよい
そして最後にpをqで割ればよい。
int N; string op[101]; ll A[101]; void solve() { int i,j,k,l,r,x,y; string s; cin>>N; FOR(i,N) { cin>>op[i+1]>>A[i+1]; } vector<string> S; int di=0; for(i=1;i<=N;i++) { if(op[i]=="+") { if(di==0) { S.push_back("add a A[" + to_string(i) + "] a"); } else { S.push_back("mul z A[" + to_string(i) + "] y"); S.push_back("add a a z"); } } if(op[i]=="*") { S.push_back("mul a A[" + to_string(i) + "] a"); } if(op[i]=="/") { if(di==0) { S.push_back("add y A[" + to_string(i) + "] y"); di=1; } else { S.push_back("mul y A[" + to_string(i) + "] y"); } } } if(di) S.push_back("div a a y"); cout<<S.size()<<endl; FORR(s,S) cout<<s<<endl; }
まとめ
これどうやって解法チェックしてるんだろと思ったら、Pをランダム生成して値を比較してた。