問題
http://community.topcoder.com/stat?c=problem_statement&pm=13389&rd=16075
数字の数列があり、その数字を2進数にしたときの末尾の0の数のリストが与えられる。
このとき、与えられた数列のうち1ずつ増加するサブ数列の数を求める。
解き方
数列に法則がないか列挙してみる。
すると、以下のように再帰の法則があるとわかる。
1が現れるとき:010
2が現れるとき:0102010
3が現れるとき:010201030102010
よって、与えられた数列の全てのサブ数列に対し、以下の法則が成り立つか
再帰を用いてチェックすればよい。
コード
using namespace std;
#define all(c) (c).begin(),(c).end()
#define FORE(i,d,e) for(int i=d;i<e;i++)
#define FOR(i,s,e) for (int i = int(s); i != int(e); i++)
#define FORIT(i,c) for (typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ISEQ(c) (c).begin(), (c).end()
class PotentialArithmeticSequence {
public:
bool can(vector<int> d){
if(d.size()==1)return true;
int p= d[0]==0 ? 0 : 1;
int n=d.size();
vector<int> next;
FORE(i,0,n){
if(i%2==p){
if(d[i]!=0)return false;
}
else{
if(d[i]==0)return false;
next.push_back(d[i]-1);
}
}
return can(next);
}
int numberOfSubsequences(vector<int> d) {
int ret=0;
int n=d.size();
FORE(i,0,n)FORE(j,i,n){
vector<int> cur;
FORE(k,i,j+1)cur.push_back(d[k]);
if(can(cur))ret++;
}
return ret;
}
};
#define all(c) (c).begin(),(c).end()
#define FORE(i,d,e) for(int i=d;i<e;i++)
#define FOR(i,s,e) for (int i = int(s); i != int(e); i++)
#define FORIT(i,c) for (typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ISEQ(c) (c).begin(), (c).end()
class PotentialArithmeticSequence {
public:
bool can(vector<int> d){
if(d.size()==1)return true;
int p= d[0]==0 ? 0 : 1;
int n=d.size();
vector<int> next;
FORE(i,0,n){
if(i%2==p){
if(d[i]!=0)return false;
}
else{
if(d[i]==0)return false;
next.push_back(d[i]-1);
}
}
return can(next);
}
int numberOfSubsequences(vector<int> d) {
int ret=0;
int n=d.size();
FORE(i,0,n)FORE(j,i,n){
vector<int> cur;
FORE(k,i,j+1)cur.push_back(d[k]);
if(can(cur))ret++;
}
return ret;
}
};