nikeeshi のコーディング記

コーディングの成果をはっつけるとこ。このブログにあるソースコードはNYSL Version 0.9982に従い公開します(2014/06/18)。

SRM 590 Div1

Easy速く解かないとレートが維持できなくなってきた。

250 駒あそび?

RとLの駒を移動させて目的の形にできるか問題。

コード

#include <string>
#include <vector>
using namespace std;
class FoxAndChess{
public:
   string ableToMove(string begin, string target){
      if(solve(begin,target))
         return string("Possible");
      else
         return string("Impossible");
   }
   bool solve(string begin, string target){
      string str[2]={begin,target};
      vector<int> pos[2];
      vector<char> type[2];
      for(int j=0;j<2;j++)
      for(int i=0;i<str[j].size();i++){
         switch(str[j][i]){
         case 'R':
            type[j].push_back('R');
            pos[j].push_back(i);
            break;
         case 'L':
            type[j].push_back('L');
            pos[j].push_back(i);
            break;
         default:
            break;
         }
      }
      if(type[0]!=type[1])return false;
      for(int i=0;i<type[0].size();i++){
         if(type[0][i]=='R'){
            if(!(pos[0][i]<=pos[1][i]))return false;
         }
         else
            if(!(pos[0][i]>=pos[1][i]))return false;
      }
      return true;
   }
};
#include <iostream>
int main(){
   FoxAndChess f;
   cout<<f.ableToMove(string("R..."),string("..R."))<<endl;
   return 0;
}

500 XOR

XORで目的の数以下を作る方法は何通りあるか。

解法

与えられた数をnumber、目的の数をlimitとする。 ここで、numberの中からaとbをとってきてbの代わりにa+b(XOR)を入れても答えは変化しないという性質を使う。 numberを掃き出し法のように簡単にしていく。 以下の性質を持った状態に変形する。

  • それぞれの要素の2進法での桁数が被らない。(その要素が0である場合を除く)
  • ソート済み

次に以下のように元の問題をsum<=limitからsum=targetの小問題に分解する。

  • numberをそのままでsum=limitとする。
  • limitの1になっている桁を0に変え、その桁が一番下の桁になるように2の累乗で割る。さらに同じだけnumberを割る。そして、sum=limitとする。

それぞれの小問題はnumberを大きい方から貪欲的にとっていけばよい。

コード

#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;
int bit(long long value,long long n){
   return (value>>n)&1;
}
//for test
void print(vector<long long> n){
   for(int i=0;i<n.size();i++){
      for(int j=3;j>=0;j--)
         cout<<bit(n[i],j);
      cout<<" ";
   }
   cout<<endl;
}
class XorCards{
public:
   long long count(vector<long long>& number,long long target,int star){
      long long ans=1;
      for(int i=0;i<number.size();i++){
         long long upper=number[i]>>star;
         if(upper==0){ans*=2;continue;}
         if((target^upper)<target)target^=upper;
      }
      if(target==0)
         return ans;
      else
         return 0;
   }
   long long numberOfWays(vector<long long> number, long long limit){
      for(int i=63;i>=0;i--){ 
         sort(number.begin(),number.end());
         for(int j=0;j<number.size();j++){
            if(bit(number[j],i)==1){
               for(int k=j+1;k<number.size();k++)
                  if(bit(number[k],i)==1)
                     number[k]=number[k]^number[j];
               break;
            }
         }
      }
      sort(number.begin(),number.end(),greater<long long>());
      long long ans=0;
      ans+=count(number,limit,0);
      for(int i=0;i<64;i++){
         if(bit(limit,i)==1)
            ans+=count(number,(limit>>i)^1,i);
      }
      return ans;
   }
};
int main(){
   XorCards x;
   long long vv[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
   vector<long long> v(sizeof(vv)/sizeof(vv[0]));
   for(int i=0;i<v.size();i++)
      v[i]=vv[i];
   long long l=1000000000000000;
   cout<<x.numberOfWays(v,l);
   return 0;
}