Problem:
Sister Ports
姉妹港
English text is not available in this practice contest.
ACM 国は正 n 角形の島国である．
n 個の角に港があり，ある角の港から時計回りに 1 から n までの番号が順番に付いている．
港は点とみなす．
ACM 国には，二種類の道路がある．
隣り合う港を繋ぐ道路
全ての隣接する港は道路で接続されている．すなわち，番号の差が 1 である港同士および港 1 と港 n の間に道路がある．この種類の道路は n 本ある．
島の内部を通る道路
一部の隣接しない港の間も，道路で接続されている．この種類の道路は m 本あり，道路 i は港 a
i
と港 b
i
を接続する．
道路は線分とみなす．ACM 国では，任意の 2 つの道路は端点以外で共有点を持たない．
図 G-1: 港と道路の例
ACM 国は，港に事故が起きた時などに備えるため，全ての港について姉妹港を決め，いつでも互いを補助できるよう準備させることにした．
全ての港について姉妹港は 1 つで，港 a が港 b の姉妹港であるとき，港 b も港 a の姉妹港である．
すなわち，n 個の港から，港が重複しない n/2 個のペアを作る．
このとき，ACM 国は，姉妹港の間には必ず道がなければならないとすることにした．
ACM 国に住む優秀なプログラマーであるあなたの仕事は，
全港に対する姉妹港の選び方の総数を計算するプログラムを作成することである．
図 G-2: 姉妹港の選び方の例（姉妹港同士の間の道路を赤色太線で表示している）
Input
入力は1つ以上のデータセットからなる．1つのデータセットは次の形式をしている．
n
m
a
1
b
1
...
a
m
b
m
先頭行は 2 つの正の整数 n, m からなり，
それぞれ ACM 国の港の数および種類 2 の道路の数を表す．
続く m 行の i 行目は 2 個の整数 a
i
, b
i
からなり，
道路 i が港 a
i
, b
i
を結ぶことを表す．
任意の 2 つの道路は端点以外で共有点を持たない．また，これらの数は以下の範囲の値をとる．
3 ≤ n ≤ 50,000
0 ≤ m ≤ 50,000
1 ≤ a
i
, b
i
≤ n
入力の終わりはふたつのゼロを含む行で表される．
Output
各データセットについて，
姉妹港の選び方の総数を 1000003 で割った余りを出力せよ．
適切な姉妹港の選び方が存在しない場合は 0 を出力せよ．
Sample Input
6 1
1 4
8 3
1 6
1 5
2 5
12 3
3 10
4 9
6 9
3 0
0 0
Output for Sample Input
3
5
7
0

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
using P=pair<ll,ll>;
template<typename T>using minque=priority_queue<T,vector<T>,greater<T>>;
template<typename T>bool chmax(T &a,const T &b){return (a<b?(a=b,true):false);}
template<typename T>bool chmin(T &a,const T &b){return (a>b?(a=b,true):false);}
template<typename T1,typename T2>istream &operator>>(istream &is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T1,typename T2,typename T3>istream &operator>>(istream &is,tuple<T1,T2,T3>&a){is>>std::get<0>(a)>>std::get<1>(a)>>std::get<2>(a);return is;}
template<typename T,size_t n>istream &operator>>(istream &is,array<T,n>&a){for(auto&i:a)is>>i;return is;}
template<typename T>istream &operator>>(istream &is,vector<T> &a){for(auto &i:a)is>>i;return is;}
template<typename T1,typename T2>void operator++(pair<T1,T2>&a,int n){a.first++,a.second++;}
template<typename T1,typename T2>void operator--(pair<T1,T2>&a,int n){a.first--,a.second--;}
template<typename T>void operator++(vector<T>&a,int n){for(auto &i:a)i++;}
template<typename T>void operator--(vector<T>&a,int n){for(auto &i:a)i--;}
#define overload3(_1,_2,_3,name,...) name
#define rep1(i,n) for(int i=0;i<(int)(n);i++)
#define rep2(i,l,r) for(int i=(int)(l);i<(int)(r);i++)
#define rep(...) overload3(__VA_ARGS__,rep2,rep1)(__VA_ARGS__)
#define reps(i,l,r) rep2(i,l,r)
#define all(x) x.begin(),x.end()
#define pcnt(x) __builtin_popcountll(x)
#define fin(x) return cout<<(x)<<'\n',static_cast<void>(0)
#define yn(x) cout<<((x)?"Yes\n":"No\n")
#define uniq(x) sort(all(x)),x.erase(unique(all(x)),x.end())
template<typename T>
inline int fkey(vector<T>&z,T key){return lower_bound(z.begin(),z.end(),key)-z.begin();}
ll myceil(ll a,ll b){return (a+b-1)/b;}
template<typename T,size_t n,size_t id=0>
auto vec(const int (&d)[n],const T &init=T()){
  if constexpr (id<n)return vector(d[id],vec<T,n,id+1>(d,init));
  else return init;
}
#ifdef LOCAL
#include<debug.h>
#define SWITCH(a,b) (a)
#else
#define debug(...) static_cast<void>(0)
#define debugg(...) static_cast<void>(0)
#define SWITCH(a,b) (b)
template<typename T1,typename T2>ostream &operator<<(ostream &os,const pair<T1,T2>&p){os<<p.first<<' '<<p.second;return os;}
#endif
struct Timer{
  clock_t start;
  Timer(){
    start=clock();
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout<<fixed<<setprecision(16);
  }
  inline double now(){return (double)(clock()-start)/1000;}
  #ifdef LOCAL
  ~Timer(){
    cerr<<"time:";
    cerr<<now();
    cerr<<"ms\n";
  }
  #endif
}timer;
void SOLVE();
int main(){
  int testcase=1;
  //cin>>testcase;
  for(int i=0;i<testcase;i++){
    SOLVE();
  }
}
#include<type_traits>
namespace Random{
  std::mt19937_64 mt(std::random_device{}());
  template<typename T>inline std::enable_if_t<std::is_integral_v<T>,T> get(){return mt();}
  template<typename T>inline std::enable_if_t<std::is_floating_point_v<T>,T> get(){return T(mt())/T(-1ull);}
  template<typename T>inline std::enable_if_t<std::is_integral_v<T>,T>range(T n){return mt()%n;}
  template<typename T>inline std::enable_if_t<std::is_integral_v<T>,T>range(T l,T r){return l+mt()%(r-l);}
  template<typename T>inline std::enable_if_t<std::is_integral_v<T>,std::pair<T,T>>distinct(T n){
    T l=mt()%n,r=mt()%(n-1);
    if(l==r)r++;
    if(l>r)std::swap(l,r);
    return std::make_pair(l,r);
  }
}
#include<concepts>
template<typename T>
constexpr std::enable_if_t<std::numeric_limits<T>::digits<=32,int>msb(T n){return n==0?-1:31-__builtin_clz(n);}
template<typename T>
constexpr std::enable_if_t<(std::numeric_limits<T>::digits>32),int>msb(T n){return n==0?-1:63-__builtin_clzll(n);}

template<typename T>
constexpr std::enable_if_t<std::numeric_limits<T>::digits<=32,int>lsb(T n){return n==0?-1:__builtin_ctz(n);}
template<typename T>
constexpr std::enable_if_t<(std::numeric_limits<T>::digits>32),int>lsb(T n){return n==0?-1:__builtin_ctzll(n);}

template<typename T>
constexpr std::enable_if_t<std::is_integral_v<T>,T>floor_pow2(T n){return n==0?0:T(1)<<msb(n);}

template<typename T>
constexpr std::enable_if_t<std::is_integral_v<T>,T>ceil_pow2(T n){return n<=1?1:T(1)<<(msb(n-1)+1);}

template<std::integral T>
constexpr T safe_div(T a,T b){return a/b-(a%b&&(a^b)<0);}
template<std::integral T>
constexpr T safe_ceil(T a,T b){return a/b+(a%b&&(a^b)>0);}
#include<initializer_list>
bool isprime(unsigned long long n)noexcept{
  using u64=unsigned long long;
  if(n<=1)return false;
  if(n%2==0)return n==2;
  u64 d=n-1;
  int s=0;
  while(!(d&1))d>>=1,s++;
  int q=63;
  while(!(d>>q))q--;
  u64 r=n;
  for(int i=0;i<5;i++)r*=2-r*n;
  auto redc=[&r,&n](__uint128_t x)->u64 {
    x=(x+__uint128_t(u64(x)*-r)*n)>>64;
    return x>=n?x-n:x;
  };
  __uint128_t r2=-__uint128_t(n)%n;
  u64 one=redc(r2);
  for(u64 base:{2,325,9375,28178,450775,9780504,1795265022}){
    if(base%n==0)continue;
    u64 a=base=redc((base%n)*r2);
    for(int i=q-1;i>=0;i--){
      a=redc(__uint128_t(a)*a);
      if(d>>i&1)a=redc(__uint128_t(a)*base);
    }
    if(a==one)continue;
    for(int i=1;a!=n-one;i++){
      if(i>=s)return false;
      a=redc(__uint128_t(a)*a);
    }
  }
  return true;
}
namespace Random{
template<typename T>
inline std::enable_if_t<std::is_integral_v<T>,T>prime(T l,T r){
  T res=0;
  while(!isprime(res))res=range(l,r);
  return res;
}
}
struct BarrettReduction{
private:
  using i64=long long;
  using u64=unsigned long long;
  using u32=unsigned int;
  using u128=__uint128_t;
  u32 m;
  u64 im;
public:
  BarrettReduction():m(0),im(0){}
  BarrettReduction(u32 n):m(n),im(u64(-1)/n+1){}
  inline i64 quo(u64 x)const{
    if(m==1)return x;
    u64 y=u64((u128(x)*im)>>64);
    u32 r=x-y*m;
    return m<=r?y-1:y;
  }
  inline u32 rem(u64 x)const{
    if(m==1)return 0;
    u64 y=u64((u128(x)*im)>>64);
    u32 r=x-y*m;
    return m<=r?r+m:r;
  }
  inline std::pair<u64,u32>quo_rem(u64 x)const{
    if(m==0)return std::make_pair(x,0);
    u64 y=u64((u128(x)*im)>>64);
    u32 r=x-y*m;
    return m<=r?std::make_pair(y-1,r+m):std::make_pair(y,r);
  }
  inline u32 pow(u32 a,u64 p)const{
    u32 res=m!=1;
    while(p){
      if(p&1)res=rem(u64(res)*a);
      a=rem(u64(a)*a);
      p>>=1;
    }
    return res;
  }
};
template<typename Key,typename Val>
struct HashMap{
  static_assert(std::is_integral_v<Key>);
private:
  const int p;
  const Val def;
  std::vector<Key>key;
  std::vector<Val>value;
  BarrettReduction brp,brp1;
  static constexpr Key none=std::numeric_limits<std::make_signed_t<Key>>::max();
public:
  struct Iterator{
    using k_itr=typename std::vector<Key>::const_iterator;
    using v_itr=typename std::vector<Val>::iterator;
    k_itr kp;
    v_itr vp;
    k_itr kp2;
    Iterator operator++(){
      ++kp,++vp;
      step();
      return *this;
    }
    inline void step(){
      while(kp!=kp2&&(*kp)==none)++kp,++vp;
    }
    std::pair<const Key&,Val&> operator*(){
      return {*kp,*vp};
    }
    bool operator!=(Iterator rhs){return kp!=rhs.kp;}
  };
  HashMap(){}
  HashMap(int n,Val def_=Val()):def(def_),p(Random::prime(n*4/3,n*4/3+1000)){
    key.resize(p,none);
    value.resize(p,def);
    brp=BarrettReduction(p);
    brp1=BarrettReduction(p-1);
  }
  Val get(const Key&k)const{
    int now=brp.rem(k);
    int of=brp1.rem(k)+1;
    while(key[now]!=none&&key[now]!=k){
      now+=of;
      if(now>=p)now-=p;
    }
    return key[now]==none?def:value[now];
  }
  Val& set(const Key&k){
    int now=brp.rem(k);
    int of=brp1.rem(k)+1;
    while(key[now]!=none&&key[now]!=k){
      now+=of;
      if(now>=p)now-=p;
    }
    key[now]=k;
    return value[now];
  }
  Val &operator[](const Key&k){return set(k);}
  const Val& exist_get(const Key&k)const{
    int now=brp.rem(k);
    int of=brp1.rem(k)+1;
    while(key[now]!=k){
      now+=of;
      if(now>=p)now-=p;
    }
    return value[now];
  }
  Iterator begin(){
    Iterator res;
    res.kp=key.begin();
    res.vp=value.begin();
    res.kp2=key.end();
    res.step();
    return res;
  }
  Iterator end(){
    Iterator res;
    res.kp=res.kp2=key.end();
    res.vp=value.end();
    return res;
  }
};
template<typename T=int>
struct Edge{
  int from,to;
  T weight;
  int index;
  Edge(int from_,int to_,T weight_=T(),int index_=-1):from(from_),to(to_),weight(weight_),index(index_){}
  Edge():from(-1),to(-1),weight(),index(-1){}
  friend std::ostream &operator<<(std::ostream &os,const Edge&e){
    os<<'[';
    os<<"from:"<<e.from;
    os<<"to:"<<e.to;
    os<<"weight:"<<e.weight;
    os<<"index:"<<e.index;
    os<<']';
    return os;
  }
};
template<typename T=int>
struct Graph{
private:
  int n;
  std::vector<Edge<T>>edge;
  std::vector<Edge<T>>g;
  std::vector<int>ptr;
  bool directed;
  struct graph_range{
    using iterator=typename std::vector<Edge<T>>::iterator;
    iterator l,r;
    iterator begin()const{return l;}
    iterator end()const{return r;}
    int size()const{return r-l;}
    Edge<T> &operator[](int i)const{return l[i];}
  };
  struct const_graph_range{
    using iterator=typename std::vector<Edge<T>>::const_iterator;
    iterator l,r;
    iterator begin()const{return l;}
    iterator end()const{return r;}
    int size()const{return r-l;}
    const Edge<T> &operator[](int i)const{return l[i];}
  };
public:
  Graph(int n_,bool dir_):n(n_),directed(dir_){}
  Graph():n(0){}
  Graph(int n_,bool dir_,const std::vector<Edge<T>>&e):n(n_),directed(dir_),edge(e){build();}
  template<bool weighted=false,bool index=1>
  void read(int m){
    edge.reserve(m);
    for(int i=0;i<m;i++){
      int u,v;
      std::cin>>u>>v;
      T w;
      if constexpr(index)u--,v--;
      if constexpr(weighted)std::cin>>w;
      else w=1;
      edge.emplace_back(u,v,w,i);
    }
    build();
  }
  void add_edge(int u,int v){
    int id=edge.size();
    edge.emplace_back(u,v,1,id);
  }
  void add_edge(int u,int v,T w){
    int id=edge.size();
    edge.emplace_back(u,v,w,id);
  }
  void add_edge(int u,int v,T w,int index){
    edge.emplace_back(u,v,w,index);
  }
  void build(){
    std::vector<int>cnt(n+1,0);
    for(const Edge<T>&e:edge){
      cnt[e.from+1]++;
      if(!directed)cnt[e.to+1]++;
    }
    for(int i=1;i<=n;i++)cnt[i]+=cnt[i-1];
    ptr=cnt;
    g.resize(cnt[n]);
    for(const Edge<T>&e:edge){
      g[cnt[e.from]++]=e;
      if(!directed)g[cnt[e.to]++]=Edge<T>(e.to,e.from,e.weight,e.index);
    }
  }
  void reverse(){
    if(directed){
      for(Edge<T>&e:edge)std::swap(e.from,e.to);
      build();
    }
  }
  inline void to_directed(){
    directed=true;
    build();
  }
  inline void to_undirected(){
    directed=false;
    build();
  }
  void reserve(int m){edge.reserve(m);}
  graph_range operator[](int i){return graph_range{g.begin()+ptr[i],g.begin()+ptr[i+1]};}
  const_graph_range operator[](int i)const{return const_graph_range{g.begin()+ptr[i],g.begin()+ptr[i+1]};}
  const Edge<T>& get_edge(int i)const{return edge[i];}
  std::vector<Edge<T>>get_edges()const{return edge;}
  inline bool is_directed()const{return directed;}
  inline int size()const{return n;}
  inline int edge_size()const{return edge.size();}
  typename std::vector<Edge<T>>::iterator begin(){return edge.begin();}
  typename std::vector<Edge<T>>::iterator end(){return edge.end();}
  typename std::vector<Edge<T>>::const_iterator begin()const{return edge.begin();}
  typename std::vector<Edge<T>>::const_iterator end()const{return edge.end();}
};
template<typename T>
std::pair<std::vector<std::pair<int,int>>,std::vector<std::array<int,3>>>nice_tree_decomposition(const Graph<T>&g){
  assert(!g.is_directed());
  std::vector<std::unordered_set<int>>adj(g.size());
  for(const Edge<T>&e:g){
    adj[e.from].insert(e.to);
    adj[e.to].insert(e.from);
  }
  std::vector<int>deg(g.size());
  std::queue<int>que;
  for(int i=0;i<g.size();i++)if((deg[i]=adj[i].size())<=2)que.push(i);
  std::vector<int>idx(g.size(),-1);
  std::vector<std::pair<int,int>>child(1);
  std::vector<std::array<int,3>>vs(1);
  auto make_nice=[&](int&ch,const std::array<int,3>&par)->void {
    std::array<int,3>ar;
    int pos1=0,pos2=0;
    while(pos1<3&&vs[ch][pos1]!=-1)pos1++;
    while(pos2<3&&par[pos2]!=-1)pos2++;
    for(int i=0;pos1>1;){
      bool found=false;
      for(;i<pos1;i++){
        if(std::find(par.begin(),par.begin()+pos2,vs[ch][i])==par.begin()+pos2){
          child.emplace_back(ch,-1);
          assert(ch!=child.size()-1);
          std::array<int,3>&fix=vs.emplace_back(vs[ch]);
          for(int j=i;j+1<3;j++)fix[j]=fix[j+1];
          fix[2]=-1;
          ch=child.size()-1;
          found=true;
          pos1--;
          break;
        }
      }
      if(!found)break;
    }
    for(int i=0;i<pos2;i++){
      if(std::find(vs[ch].begin(),vs[ch].begin()+pos1,par[i])==vs[ch].begin()+pos1){
        child.emplace_back(ch,-1);
        std::array<int,3>&fix=vs.emplace_back(vs[ch]);
        fix[pos1++]=par[i];
        ch=child.size()-1;
      }
    }
  };
  auto merge=[&](int lc,int rc,const std::array<int,3>&par)->int {
    make_nice(lc,par);
    make_nice(rc,par);
    child.emplace_back(lc,rc);
    vs.emplace_back(par);
    return child.size()-1;
  };
  while(!que.empty()){
    int x=que.front();que.pop();
    if(idx[x]!=-1)continue;
    std::array<int,3>v;
    v[0]=x;
    v[1]=v[2]=-1;
    for(int y:adj[x]){
      if(idx[y]==-1){
        if(v[1]==-1)v[1]=y;
        else v[2]=y;
      }
    }
    std::pair<int,int>c=std::make_pair(-1,-1);
    for(int y:adj[x])if(idx[y]>=0){
      if(c.first==-1)c.first=idx[y];
      else if(c.second==-1)c.second=idx[y];
      else{
        c.first=merge(c.first,c.second,v);
        c.second=idx[y];
      }
      idx[y]=-2;
    }
    deg[x]=0;
    if(c.first==-1){
      idx[x]=child.size();
      child.emplace_back(c);
      vs.emplace_back(std::move(v));
      int u=idx[x];
      if(vs[u][2]!=-1){
        child[u].first=child.size();
        child.emplace_back(-1,-1);
        vs.emplace_back(vs[u])[2]=-1;
        u=child.size()-1;
      }
      if(vs[u][1]!=-1){
        child[u].first=child.size();
        child.emplace_back(-1,-1);
        vs.emplace_back(vs[u])[1]=-1;
        u=child.size()-1;
      }
    }
    else if(c.second==-1){
      make_nice(c.first,v);
      idx[x]=c.first;
    }
    else{
      idx[x]=merge(c.first,c.second,v);
    }
    if(v[1]!=-1){
      if(v[2]!=-1){
        if(adj[v[1]].contains(v[2])){
          for(int i=1;i<=2;i++){
            if(--deg[v[i]]<=2&&idx[v[i]]==-1)que.push(v[i]);
          }
        }
        else{
          adj[v[1]].insert(v[2]);
          adj[v[2]].insert(v[1]);
        }
      }
      else if(--deg[v[1]]<=2&&idx[v[1]]==-1)que.push(v[1]);
    }
  }
  if(std::any_of(deg.begin(),deg.end(),[](int x){return x!=0;}))return {{},{}};
  child[0]=std::move(child.back()),child.pop_back();
  vs[0]=std::move(vs.back()),vs.pop_back();
  que.push(0);
  while(!que.empty()){
    int x=que.front();que.pop();
    if(child[x].second!=-1){
      vs[child[x].first]=vs[child[x].second]=vs[x];
      que.push(child[x].first);
      que.push(child[x].second);
    }
    else if(child[x].first!=-1){
      std::array<int,3>nxt=vs[x];
      std::array<int,3>&nc=vs[child[x].first];
      if(std::count(vs[x].begin(),vs[x].end(),-1)<std::count(nc.begin(),nc.end(),-1)){
        for(int i=0;i<3;i++){
          if(nxt[i]!=-1&&std::find(nc.begin(),nc.end(),nxt[i])==nc.end()){
            nxt[i]=-1;
          }
        }
      }
      else{
        for(int i=0;i<3;i++){
          if(nc[i]!=-1&&std::find(vs[x].begin(),vs[x].end(),nc[i])==vs[x].end()){
            nxt[std::find(nxt.begin(),nxt.end(),-1)-nxt.begin()]=nc[i];
          }
        }
      }
      nc=std::move(nxt);
      que.push(child[x].first);
    }
  }
  return std::make_pair(std::move(child),std::move(vs));
}
#include<optional>
constexpr int carmichael_constexpr(int n){
  if(n==998244353)return 998244352;
  if(n==1000000007)return 1000000006;
  if(n<=1)return n;
  int res=1;
  int t=0;
  while(n%2==0){
    n/=2;
    t++;
  }
  if(t==2)res=2;
  else if(t>=3)res=1<<(t-2);
  for(int i=3;i*i<=n;i++)if(n%i==0){
    int c=0;
    while(n%i==0){
      n/=i;
      c++;
    }
    int prod=i-1;
    for(int j=0;j<c-1;j++)prod*=i;
    res=std::lcm(res,prod);
  }
  if(n!=1)res=std::lcm(res,n-1);
  return res;
}
template<int m>
struct mod_int{
private:
  static constexpr unsigned int umod=static_cast<unsigned int>(m);
  static constexpr unsigned int car=carmichael_constexpr(m);
  using uint=unsigned int;
  using mint=mod_int;
  uint v;
  static_assert(m<uint(1)<<31);
  mint sqrt_impl()const{
    if(this->val()<=1)return *this;
    if constexpr(m%8==1){
      mint b=2;
      while(b.pow((m-1)/2).val()==1)b++;
      int m2=m-1,e=0;
      while(m2%2==0)m2>>=1,e++;
      mint x=this->pow((m2-1)/2);
      mint y=(*this)*x*x;
      x*=*this;
      mint z=b.pow(m2);
      while(y.val()!=1){
        int j=0;
        mint t=y;
        while(t.val()!=1)t*=t,j++;
        z=z.pow(1<<(e-j-1));
        x*=z;
        z*=z;
        y*=z;e=j;
      }
      return x;
    }
    else if constexpr(m%8==5){
      mint ret=this->pow((m+3)/8);
      if((ret*ret).val()==this->val())return ret;
      else return ret*mint::raw(2).pow((m-1)/4);
    }
    else{
      return this->pow((m+1)/4);
    }
  }
public:
  using value_type=uint;
  mod_int():v(0){}
  template<typename T,std::enable_if_t<std::is_signed_v<T>,std::nullptr_t> =nullptr>
  mod_int(T a){
    a%=m;
    if(a<0)v=a+umod;
    else v=a;
  }
  template<typename T,std::enable_if_t<std::is_unsigned_v<T>,std::nullptr_t> =nullptr>
  mod_int(T a):v(a%umod){}
  static constexpr mint raw(int a){
    mint ret;
    ret.v=a;
    return ret;
  }
  inline uint val()const{return this->v;}
  static constexpr int mod(){return m;}
  inline mint &operator+=(const mint &b){
    this->v+=b.v;
    if(this->v>=umod)this->v-=umod;
    return *this;
  }
  inline mint &operator-=(const mint &b){
    this->v-=b.v;
    if(this->v>=umod)this->v+=umod;
    return *this;
  }
  inline mint &operator*=(const mint &b){
    this->v=((unsigned long long)this->v*b.v)%umod;
    return *this;
  }
  inline mint &operator/=(const mint &b){
    *this*=b.inv();
    return *this;
  }
  inline mint operator+()const{return *this;}
  inline mint operator-()const{return mint()-*this;}
  friend inline mint operator+(const mint &a,const mint &b){return mint(a)+=b;}
  friend inline mint operator-(const mint &a,const mint &b){return mint(a)-=b;}
  friend inline mint operator*(const mint &a,const mint &b){return mint(a)*=b;}
  friend inline mint operator/(const mint &a,const mint &b){return mint(a)/=b;}
  friend inline bool operator==(const mint &a,const mint &b){return a.val()==b.val();}
  friend inline bool operator!=(const mint &a,const mint &b){return !(a==b);}
  inline mint operator++(int){
    mint ret=*this;
    *this+=mint::raw(1);
    return ret;
  }
  inline mint operator--(int){
    mint ret=*this;
    *this-=mint::raw(1);
    return ret;
  }
  mint pow(long long n)const{
    mint ret=mint::raw(1),a(*this);
    while(n){
      if(n&1)ret*=a;
      a*=a;
      n>>=1;
    }
    return ret;
  }
  inline mint inv()const{
    assert(this->v!=0);
    return pow(car-1);
  }
  std::optional<mint>sqrt()const{
    if(this->val()<=1||this->pow((m-1)/2)==1)return std::make_optional(this->sqrt_impl());
    else return std::nullopt;
  }
  static constexpr unsigned int order(){return car;}
  friend std::istream &operator>>(std::istream &is,mint &b){
    long long a;
    is>>a;
    b=mint(a);
    return is;
  }
  friend std::ostream &operator<<(std::ostream &os,const mint &b){
    os<<b.val();
    return os;
  }
};
template<int m>
struct std::hash<mod_int<m>>{
  std::size_t operator()(mod_int<m>x)const{
    return std::hash<unsigned int>()(x.val());
  }
};
using mint998=mod_int<998244353>;
using mint107=mod_int<1000000007>;
using mint=mod_int<1000003>;
void SOLVE(){
  while(true){
    int n,m;
    cin>>n>>m;
    if(n==0)break;
    if(n&1){
      cout<<"0\n";
      continue;
    }
    Graph g(n,false);
    g.reserve(n+m);
    HashMap<ll,char>mp(n+m);
    auto add_edge=[&](int u,int v)->void {
      if(u>v)swap(u,v);
      mp[ll(u)*n+v]=true;
      g.add_edge(u,v);
    };
    auto find_edge=[&](int u,int v)->bool {
      if(u>v)swap(u,v);
      if(u==-1)return false;
      return mp.get(ll(u)*n+v);
    };
    rep(i,n)add_edge(i,(i+1)%n);
    rep(i,m){
      int u,v;
      cin>>u>>v;
      u--,v--;
      add_edge(u,v);
    }
    g.build();
    auto result=nice_tree_decomposition(g);
    auto child=result.first;
    auto vs=result.second;
    using Data=array<mint,8>;
    auto dfs=[&](auto self,int x)->Data {
      if(child[x].first==-1){
        Data res;
        res.fill(0);
        res[0]=1;
        return res;
      }
      else if(child[x].second==-1){
        int c=child[x].first;
        int pos=0;
        while(vs[x][pos]==vs[c][pos])pos++;
        Data cdp=self(self,c);
        Data res;
        res.fill(0);
        if(vs[x][pos]==-1){//forget
          rep(i,8){
            if(i>>pos&1)res[i^(1<<pos)]+=cdp[i];
            else{
              rep(j,3)if(pos!=j&&!(i>>j&1)&&find_edge(vs[c][pos],vs[c][j])){
                res[i|(1<<j)]+=cdp[i];
              }
            }
          }
        }
        else{
          res=cdp;
        }
        return res;
      }
      else{
        auto ldp=self(self,child[x].first);
        auto rdp=self(self,child[x].second);
        Data res;
        res.fill(0);
        rep(i,8)rep(j,8){
          if(i&j)continue;
          res[i|j]+=ldp[i]*rdp[j];
        }
        return res;
      }
    };
    auto dp=dfs(dfs,0);
    int mask=0;
    rep(i,3)if(vs[0][i]!=-1)mask|=1<<i;
    cout<<dp[mask]<<'\n';
  }
}
accuracy: 1
time_ms: 210
memory_kb: 56404
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
#define all(A) A.begin(),A.end()
#define ALL(A) A.begin(),A.end()
#define rep(i, n) for (ll i = 0; i < (ll) (n); i++)
template<class T>
bool chmax(T& p, T q, bool C = 1) {
    if (C == 0 && p == q) {
        return 1;
    }
    if (p < q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

template<class T>
bool chmin(T& p, T q, bool C = 1) {
    if (C == 0 && p == q) {
        return 1;
    }
    if (p > q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

map<pair<pair<ll,ll>,ll>,ll> DP;
vector<set<ll>> G;
vector<ll> Rightest;
const ll mod=1000003;

void dfs(ll L,ll R){
    if(L>=R)return;
    if(L+1==R){
        DP[{{L,R},0}]=1;
        DP[{{L,R},3}]=1;
        return;
    }
    ll mid=R-1;
    if(Rightest[R]>L){
        mid=*(G[R].upper_bound(L));
    }
    if((mid-L)!=1){
        dfs(L,mid);
    }
    else{
        DP[{{L,mid},0}]=1;
        DP[{{L,mid},3}]=1;
    }
    if((R-mid)!=1){
        dfs(mid,R);
    }
    else{
        DP[{{mid,R},0}]=1;
        DP[{{mid,R},3}]=1;
    }
    

    rep(lbit,4)rep(rbit,4){
        ll d=(lbit%2)+(rbit/2);
        if(d!=1)continue;
        ll nl=lbit/2;
        ll nr=rbit%2;
        DP[{{L,R},nl*2+nr}]+=DP[{{L,mid},lbit}]*DP[{{mid,R},rbit}]%mod;
        if(nl*2+nr==0&&G[L].count(R)){
            DP[{{L,R},3}]+=DP[{{L,mid},lbit}]*DP[{{mid,R},rbit}]%mod;
        }
    }
    rep(i,4){
        DP[{{L,R},i}]%=mod;
    }
    return;

    
}


void solve(ll N,ll M) {
    DP.clear();
    G.resize(N);
    rep(i,N)G[i].clear();
    Rightest.assign(N,-1e18);
    Rightest[N-1]=0;
    rep(i,M){
        ll A,B;
        cin>>A>>B;
        A--,B--;
        if(A>B)swap(A,B);
        if((B-A)%2==1){
            G[A].insert(B);
            G[B].insert(A);
            Rightest[B]=max(Rightest[B],A);
        }
    }
    G[0].insert(N-1);
    if(N%2==1){
        cout<<0<<endl;
        return;
    }

    dfs(0,N-1);
    cout<<DP[{{0,N-1},3}]<<endl;
    
}


int main() {

    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    ll N,K;
    while (cin >> N>>K, N != 0)solve(N,K);

}
accuracy: 1
time_ms: 1120
memory_kb: 49480
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;

bool is_end = false;
const ll MOD = 1000003;

ll calc_dp(int left, int right, map<array<int, 2>, int> &mp, const vector<vector<ll>> &edge, const vector<int> &next_v)
{
    // cout << left << " " << right << endl;
    assert(left % 2 == right % 2);
    
    if (left >= right)
    {
        return 1;
    }
    if (mp.find({left, right}) != mp.end())
    {
        return mp[{left, right}];
    }
    
    ll ret = 0;
    for (auto mid : edge[left])
    {
        ret += calc_dp(left + 1, mid - 1, mp, edge, next_v) * calc_dp(next_v[mid], right, mp, edge, next_v);
    }
    return mp[{left, right}] = ret % MOD;
}


void solve()
{
    ll N, M; cin >> N >> M;
    if (N == 0 && M == 0)
    {
        is_end = true;
        return;
    }
    
    if (N % 2 == 1)
    {
        cout << 0 << endl;
        return;
    }
    
    vector<vector<ll>> edge(N);
    for (int i = 0; i < M; ++i)
    {
        ll a, b; cin >> a >> b;
        a--, b--;
        ll c = min(a, b), d = max(a, b) + 1;
        if (c % 2 == d % 2) edge[c].emplace_back(d);
    }
    vector<int> next_v(N+1, 0);
    {
        ll nxt = N;
        for (int i = N; i >= 0; i -= 2)
        {
            if (edge[i].size()) nxt = i;
            next_v[i] = nxt;
        }
        nxt = N - 1;
        for (int i = N - 1; i >= 0; i -= 2)
        {
            if (edge[i].size()) nxt = i;
            next_v[i] = nxt;
        }
        
        // for (int i = 0; i < N; ++i)
        // {
        //     cout << i << " " << next_v[i] << endl;
        // }
    }
    
    for (int i = 0; i < N - 1; ++i)
    {
        edge[i].emplace_back(i+2);
    }
    edge[0].emplace_back(N);
    for (int i = 0; i < N; ++i)
    {
        sort(edge[i].begin(), edge[i].end());
    }
    
    map<array<int, 2>, int> mp;
    ll res = calc_dp(0, N, mp, edge, next_v);
    cout << res << endl;
    
    return;
}


int main()
{
    while (!is_end)
    {
        solve();
    }
    
    return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 14124
final_rank: 7

code_snippet: // #pragma GCC target("avx2")
#pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
// #include<sys/time.h>
// #include<atcoder/fenwicktree>

using namespace std;

// using mint = atcoder::modint1000000007;

using P = pair<int, int>;

const int mod = 1000003;
vector<vector<int>> edge;

array<long long, 4> dfs(int l, int r) {
    if (l == r - 1) {
        return { 1, 0, 0, 1 };
    }
    bool lr = false;
    if (edge[l].back() == r) {
        lr = true;
        edge[l].pop_back();
    }
    int m = edge[l].back();
    auto vl = dfs(l, m);
    auto vr = dfs(m, r);
    array<long long, 4> res{};
    res[0] = (vl[0] * vr[2] + vl[1] * vr[0]) % mod;
    res[1] = (vl[0] * vr[3] + vl[1] * vr[1]) % mod;
    res[2] = (vl[2] * vr[2] + vl[3] * vr[0]) % mod;
    res[3] = (vl[2] * vr[3] + vl[3] * vr[1]) % mod;
    if (lr) {
        res[3] = (res[3] + vl[0] * vr[2] + vl[1] * vr[0]) % mod;
    }
    return res;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(0);
    while (true) {
        int n, m;
        cin >> n >> m;
        if (n == 0) break;

        edge = vector<vector<int>>(n);
        for (int i = 0; i + 1 < n; ++i) {
            edge[i].push_back(i + 1);
        }
        edge[0].push_back(n - 1);
        for (int i = 0; i < m; ++i) {
            int u, v;
            cin >> u >> v;
            --u;
            --v;
            if (u > v) {
                swap(u, v);
            }
            edge[u].push_back(v);
        }
        for (int i = 0; i < n; ++i) {
            sort(edge[i].begin(), edge[i].end());
        }
        auto res = dfs(0, n - 1);
        cout << res[3] << '\n';
    }

    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 15316
final_rank: 6

code_snippet: // #pragma GCC target("avx2")
#pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
// #include<sys/time.h>
// #include<atcoder/fenwicktree>

using namespace std;

// using mint = atcoder::modint1000000007;

using P = pair<int, int>;

const int mod = 1000003;
vector<vector<int>> edge;
unordered_map<long long, array<long long, 4>> memo;

array<long long, 4> dfs(int l, int r) {
    if (l == r - 1) {
        return { 1, 0, 0, 1 };
    }
    long long h = l * (long long)mod + r;
    if (memo.count(h)) {
        return memo[h];
    }
    bool lr = false;
    if (edge[l].back() == r) {
        lr = true;
        edge[l].pop_back();
    }
    int m = edge[l].back();
    auto vl = dfs(l, m);
    auto vr = dfs(m, r);
    array<long long, 4> res{};
    res[0] = (vl[0] * vr[2] + vl[1] * vr[0]) % mod;
    res[1] = (vl[0] * vr[3] + vl[1] * vr[1]) % mod;
    res[2] = (vl[2] * vr[2] + vl[3] * vr[0]) % mod;
    res[3] = (vl[2] * vr[3] + vl[3] * vr[1]) % mod;
    if (lr) {
        res[3] = (res[3] + vl[0] * vr[2] + vl[1] * vr[0]) % mod;
    }
    return memo[h] = res;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(0);
    while (true) {
        int n, m;
        cin >> n >> m;
        if (n == 0) break;

        edge = vector<vector<int>>(n);
        memo = unordered_map<long long, array<long long, 4>>();
        for (int i = 0; i + 1 < n; ++i) {
            edge[i].push_back(i + 1);
        }
        edge[0].push_back(n - 1);
        for (int i = 0; i < m; ++i) {
            int u, v;
            cin >> u >> v;
            --u;
            --v;
            if (u > v) {
                swap(u, v);
            }
            edge[u].push_back(v);
        }
        for (int i = 0; i < n; ++i) {
            sort(edge[i].begin(), edge[i].end());
        }
        auto res = dfs(0, n - 1);
        cout << res[3] << '\n';
    }

    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 19480
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define rep(i, n) for (int i = 0; i < (n); i++)
#define per(i, n) for (int i = (n)-1; i >= 0; i--)
#define rep2(i, l, r) for (int i = (l); i < (r); i++)
#define per2(i, l, r) for (int i = (r)-1; i >= (l); i--)
#define each(e, x) for (auto &e : x)
#define sz(x) (int)x.size()
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define eb emplace_back
#define MM << ' ' <<
#define TT template <typename T>
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

TT bool chmin(T &x, T y) { return x > y ? (x = y, true) : false; }
TT bool chmax(T &x, T y) { return x < y ? (x = y, true) : false; }

TT using minheap = priority_queue<T, vector<T>, greater<T>>;
TT using maxheap = priority_queue<T>;

TT void print(vector<T> v, T x = 0) {
    int n = sz(v);
    rep(i, n) cout << v[i] + x << (i == n - 1 ? '\n' : ' ');
    if (n == 0) cout << '\n';
}

TT void printn(vector<T> v, T x = 0) {
    int n = sz(v);
    rep(i, n) cout << v[i] + x << '\n';
}

TT void rearrange(vector<T> &v) {
    sort(all(v));
    v.erase(unique(all(v)), end(v));
}

TT int lb(vector<T> &v, T x) { return lower_bound(all(v), x) - begin(v); }
TT int ub(vector<T> &v, T x) { return upper_bound(all(v), x) - begin(v); }

const int inf = (1 << 30) - 1;
const ll INF = (1LL << 60) - 1;

struct io_setup {
    io_setup() {
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        cout << fixed << setprecision(15);
    }
} io_setup;

template <int mod>
struct modint {
    int x;

    modint() : x(0) {}

    modint(ll y) {
        x = y % mod;
        if (x < 0) x += mod;
    }

    static int get_mod() { return mod; }

    modint &operator+=(modint p) {
        x += p.x;
        if (x >= mod) x -= mod;
        return *this;
    }

    modint &operator-=(modint p) {
        x -= p.x;
        if (x < 0) x += mod;
        return *this;
    }

    modint &operator*=(modint p) {
        x = (1LL * x * p.x) % mod;
        return *this;
    }

    modint &operator/=(modint p) {
        *this *= p.inverse();
        return *this;
    }

    modint operator-() { return modint(-x); }
    modint operator+(modint p) { return modint(*this) += p; }
    modint operator-(modint p) { return modint(*this) -= p; }
    modint operator*(modint p) { return modint(*this) *= p; }
    modint operator/(modint p) { return modint(*this) /= p; }
    bool operator==(modint p) { return x == p.x; }
    bool operator!=(modint p) { return x != p.x; }

    modint pow(ll k) {
        modint ret = 1, now = *this;
        while (k > 0) {
            if (k & 1) ret *= now;
            now *= now;
            k >>= 1;
        }
        return ret;
    }

    modint inverse() { return pow(mod - 2); }

    friend istream &operator>>(istream &is, modint &p) {
        ll y;
        is >> y;
        p = modint(y);
        return is;
    }

    friend ostream &operator<<(ostream &os, modint p) { return os << p.x; }
};

using mint = modint<1000003>;

void solve() {
    int N, M;
    cin >> N >> M;

    if (N == 0 && M == 0) exit(0);

    vector<int> IN(N, 0), OUT(N, 0);

    rep(i, M) {
        int u, v;
        cin >> u >> v;
        u--, v--;
        if (u > v) swap(u, v);
        if (u % 2 == v % 2) continue;
        IN[u]++, OUT[v]++;
    }

    IN[0]++, OUT[N - 1]++;

    if (N & 1) {
        cout << 0 << '\n';
        return;
    }

    vector<int> l, r;
    vector<vector<int>> es;

    stack<int> st;

    rep(i, N) {
        rep(j, OUT[i]) {
            assert(!empty(st));
            int v = st.top();
            st.pop();
            r[v] = i;
            if (!empty(st)) {
                int p = st.top();
                es[p].eb(v);
            }
        }
        rep(j, IN[i]) {
            int v = sz(l);
            l.eb(i), r.eb(-1);
            es.eb();
            st.emplace(v);
        }
    }

    auto rec = [&](auto &&rec, int now) -> pair<mint, mint> {
        int L = sz(es[now]);
        vector<pair<mint, mint>> ps(L);
        rep(i, L) {
            int e = es[now][i];
            ps[i] = rec(rec, e);
        }

        auto count = [&](int s) {
            mint ret = 1;
            rep(i, L) {
                int e = es[now][i];
                if (l[e] < s || l[e] % 2 != s % 2) {
                    ret *= ps[i].second;
                } else {
                    ret *= ps[i].first;
                }
            }
            return ret;
        };

        mint x = count(l[now]), y = count(l[now] + 1);

        return make_pair(x + y, y);
    };

    auto [x, y] = rec(rec, 0);
    cout << x << '\n';
}

int main() {
    while (true) solve(); //
}
accuracy: 1
time_ms: 20
memory_kb: 7848
final_rank: 3

code_snippet: #include <iostream>
#include <set>
#include <vector>
using namespace std;

const long long mod = 1000003;
long long N;
long long M, A[200009], B[200009];
long long DP[200009][3];
long long NumArea = 1;
set<pair<int, int>> Set;
vector<pair<int, int>> G[200009];

void Initialize() {
	NumArea = 1;
	Set.clear();
	for (int i = 0; i < 200000; i++) {
		A[i] = 0; B[i] = 0; G[i].clear();
		for (int j = 0; j < 3; j++) DP[i][j] = 0;
	}
}

void dfs(int pos, int cl, int cr) {
	vector<pair<int, int>> Edges;
	int cur = cl; if (cl == -1) cur = 0;
	int target = cr; if (cr == -1) target = 100000000;

	// Get Childs
	while (true) {
		auto itr = Set.lower_bound(make_pair(cur, -target));
		if (Edges.size() == 0 || (cl == -1 && Edges.size() == 1)) itr = Set.lower_bound(make_pair(cur, -target + 1));

		// Add Edges
		int pl = (*itr).first;
		int pr = -(*itr).second;
		if (cr != -1 && pl >= cr) break;
		if (cr == -1 && Edges.size() >= 1 && pl >= Edges[0].first + N) break;
		Edges.push_back(make_pair(pl, pr));
		cur = pr;
		if (cr == -1 && Edges.size() == 1) target = pl + N;
	}

	// DFS
	int BASE = NumArea; NumArea += Edges.size();
	for (int i = 0; i < Edges.size(); i++) {
		int col = Edges[i].first % 2;
		if (Edges[i].first % 2 == Edges[i].second % 2) col = -1;
		G[pos].push_back(make_pair(BASE + i, col));
	}
	for (int i = 0; i < Edges.size(); i++) dfs(BASE + i, Edges[i].first, Edges[i].second);
}

void dfs2(int pos) {
	// Recursion
	for (pair<int, int> i : G[pos]) dfs2(i.first);
	long long Way0 = 1;
	long long Way1 = 1;
	long long WayN = 1;

	// Multiplication
	for (int i = 0; i < G[pos].size(); i++) {
		int to = G[pos][i].first;
		int col = G[pos][i].second;
		if (col == 0) Way0 *= (DP[to][0] + DP[to][1] + DP[to][2] + DP[to][2]);
		if (col != 0) Way0 *= (DP[to][0] + DP[to][2]);
		if (col == 1) Way1 *= (DP[to][0] + DP[to][1] + DP[to][2] + DP[to][2]);
		if (col != 1) Way1 *= (DP[to][1] + DP[to][2]);
		WayN *= DP[to][2];
		Way0 %= mod; Way1 %= mod; WayN %= mod;
	}
	DP[pos][0] += (Way0 - WayN + mod) % mod;
	DP[pos][1] += (Way1 - WayN + mod) % mod;
	DP[pos][2] += WayN;
}

int main() {
	while (true) {
		// Step 1. Input
		Initialize();
		cin >> N >> M; if (N + M == 0) break;
		for (int i = 0; i < M; i++) cin >> A[i] >> B[i];
		for (int i = 0; i < M; i++) A[i] -= 1;
		for (int i = 0; i < M; i++) B[i] -= 1;
		for (int i = 0; i < M; i++) {
			if (A[i] > B[i]) swap(A[i], B[i]);
		}
		if (N % 2 == 1) {
			cout << "0" << endl;
			continue;
		}
		if (M == 0) {
			cout << "2" << endl;
			continue;
		}

		// Step 2. Make Tree
		for (int i = 0; i < M; i++) Set.insert(make_pair(A[i] + N * 0, -(B[i] + N * 0)));
		for (int i = 0; i < M; i++) Set.insert(make_pair(B[i] + N * 0, -(A[i] + N * 1)));
		for (int i = 0; i < M; i++) Set.insert(make_pair(A[i] + N * 1, -(B[i] + N * 1)));
		for (int i = 0; i < M; i++) Set.insert(make_pair(B[i] + N * 1, -(A[i] + N * 2)));
		for (int i = 0; i < M; i++) Set.insert(make_pair(A[i] + N * 2, -(B[i] + N * 2)));
		for (int i = 0; i < M; i++) Set.insert(make_pair(B[i] + N * 2, -(A[i] + N * 3)));
		dfs(0, -1, -1);

		// Step 3. Get Answer
		dfs2(0);
		cout << (DP[0][0] + DP[0][1] + 2LL) % mod << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 360
memory_kb: 37540
final_rank: 9

code_snippet: #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2405&lang=jp"

#include <iostream>
#include <map>
#include <set>

constexpr int mod = 1000003;

#include <functional>

#include <algorithm>

#include <cassert>
#include <vector>

namespace atcoder {

// Implement (union by size) + (path compression)
// Reference:
// Zvi Galil and Giuseppe F. Italiano,
// Data structures and algorithms for disjoint set union problems
struct dsu {
  public:
    dsu() : _n(0) {}
    explicit dsu(int n) : _n(n), parent_or_size(n, -1) {}

    int merge(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        int x = leader(a), y = leader(b);
        if (x == y) return x;
        if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
        parent_or_size[x] += parent_or_size[y];
        parent_or_size[y] = x;
        return x;
    }

    bool same(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        return leader(a) == leader(b);
    }

    int leader(int a) {
        assert(0 <= a && a < _n);
        if (parent_or_size[a] < 0) return a;
        return parent_or_size[a] = leader(parent_or_size[a]);
    }

    int size(int a) {
        assert(0 <= a && a < _n);
        return -parent_or_size[leader(a)];
    }

    std::vector<std::vector<int>> groups() {
        std::vector<int> leader_buf(_n), group_size(_n);
        for (int i = 0; i < _n; i++) {
            leader_buf[i] = leader(i);
            group_size[leader_buf[i]]++;
        }
        std::vector<std::vector<int>> result(_n);
        for (int i = 0; i < _n; i++) {
            result[i].reserve(group_size[i]);
        }
        for (int i = 0; i < _n; i++) {
            result[leader_buf[i]].push_back(i);
        }
        result.erase(
            std::remove_if(result.begin(), result.end(),
                           [&](const std::vector<int>& v) { return v.empty(); }),
            result.end());
        return result;
    }

  private:
    int _n;
    // root node: -1 * component size
    // otherwise: parent
    std::vector<int> parent_or_size;
};

}  // namespace atcoder

#include <deque>
#include <optional>
#include <utility>

namespace suisen {
    struct DecompNode {
        std::vector<int> bag;
        std::vector<int> adj;
    };
    struct DecompNodeRooted {
        std::vector<int> bag;
        int par;
        std::vector<int> ch;
    };

    struct TreeDecompositionTW2 {
        TreeDecompositionTW2(const int n = 0, const std::vector<std::pair<int, int>>& edges = {}) : _n(n), _edges(edges) {}
        TreeDecompositionTW2(const std::vector<std::vector<int>>& g) : TreeDecompositionTW2(g.size()) {
            for (int i = 0; i < _n; ++i) for (int j : g[i]) if (i < j) add_edge(i, j);
        }

        void add_edge(int u, int v) {
            _edges.emplace_back(u, v);
        }

        std::optional<std::vector<DecompNode>> decomp() const {
            std::vector<std::vector<std::pair<int, int>>> g(_n);
            for (auto [u, v] : _edges) if (u != v) {
                if (u > v) std::swap(u, v);
                const int du = g[u].size(), dv = g[v].size();
                g[u].emplace_back(v, dv);
                g[v].emplace_back(u, du);
            }

            std::vector<int8_t> seen(_n, false);
            std::deque<int> dq;
            auto push_if_removable = [&](int i) {
                if (g[i].size() > 2 or std::exchange(seen[i], true)) return;
                if (g[i].size() == 2) dq.push_back(i);
                else dq.push_front(i);
            };
            for (int i = 0; i < _n; ++i) push_if_removable(i);

            std::vector<int> roots;
            std::vector<std::pair<int, int>> edges;
            edges.reserve(_n - 1);
            std::vector<std::vector<int>> bag(_n);
            std::vector<std::vector<int>> link(_n);

            atcoder::dsu uf(_n);
            for (int id = 0; id < _n; ++id) {
                if (dq.empty()) return std::nullopt;
                int u = dq.front();
                dq.pop_front();
                if (g[u].size() == 0) {
                    bag[id] = { u };
                    roots.push_back(id);
                } else if (g[u].size() == 1) {
                    int v = remove_edge(g, u, 0);
                    push_if_removable(v);
                    bag[id] = { u, v };
                    link[v].push_back(id);
                } else {
                    int v = remove_edge(g, u, 0);
                    int w = remove_edge(g, u, 0);
                    if (v > w) std::swap(v, w);
                    bag[id] = { u, v, w };
                    const int dv = g[v].size(), dw = g[w].size();
                    g[v].emplace_back(w, dw);
                    g[w].emplace_back(v, dv);
                    remove_multiedges(g, v, dv);
                    remove_multiedges(g, w, dw);
                    push_if_removable(v);
                    push_if_removable(w);
                    link[v].push_back(id);
                    link[w].push_back(id);
                }
                std::reverse(link[u].begin(), link[u].end());
                for (int id2 : link[u]) if (not uf.same(id, id2)) {
                    edges.emplace_back(id, id2);
                    uf.merge(id, id2);
                }
                g[u].clear(), g[u].shrink_to_fit(), link[u].clear(), link[u].shrink_to_fit();
            }
            const int root_num = roots.size();
            for (int i = 0; i < root_num - 1; ++i) {
                edges.emplace_back(roots[i], roots[i + 1]);
            }
            std::vector<DecompNode> res(_n);
            for (int i = 0; i < _n; ++i) {
                res[i].bag = std::move(bag[i]);
                std::sort(res[i].bag.begin(), res[i].bag.end());
            }
            for (auto& [i, j] : edges) {
                res[i].adj.push_back(j);
                res[j].adj.push_back(i);
            }
            return res;
        }
        std::optional<std::vector<DecompNodeRooted>> nice_decomp() const {
            auto opt_decomp = decomp();
            if (not opt_decomp.has_value()) return std::nullopt;
            std::vector<DecompNodeRooted> res(_n);
            for (int i = 0; i < _n; ++i) {
                res[i].bag = std::move((*opt_decomp)[i].bag);
            }

            const int root = 0;

            std::vector<std::vector<std::pair<int, int>>> adj_idx(_n);
            for (int i = 0; i < _n; ++i) for (int j : (*opt_decomp)[i].adj) if (i < j) {
                int u = i, v = j;
                auto fix_deg = [&](int& z) {
                    if ((z == root) + adj_idx[z].size() != 3) return;
                    const int n = res.size();
                    const int idx_zw = 0;
                    const auto [w, idx_wz] = adj_idx[z][idx_zw];
                    auto& node = res.emplace_back();
                    node.bag = res[z].bag;
                    adj_idx.push_back({ { z, idx_zw }, { w, idx_wz } });
                    adj_idx[z][idx_zw] = { n, 0 };
                    adj_idx[w][idx_wz] = { n, 1 };
                    z = n;
                };
                fix_deg(u), fix_deg(v);
                const int du = adj_idx[u].size(), dv = adj_idx[v].size();
                adj_idx[u].emplace_back(v, dv);
                adj_idx[v].emplace_back(u, du);
            }
            for (int i = 0; i < int(res.size()); ++i) {
                res[i].ch.reserve(adj_idx[i].size());
                for (auto [j, idx] : adj_idx[i]) res[i].ch.push_back(j);
                adj_idx[i].clear(), adj_idx[i].shrink_to_fit();
            }
            adj_idx.clear(), adj_idx.shrink_to_fit();

            std::deque<int> dq{ root };
            while (dq.size()) {
                int u = dq.front();
                dq.pop_front();
                for (int v : res[u].ch) {
                    res[v].par = u;
                    res[v].ch.erase(std::find(res[v].ch.begin(), res[v].ch.end(), u));
                    dq.push_back(v);
                }

                auto fix_path = [&](int u, int v) {
                    std::vector<int> dif;
                    std::set_difference(res[v].bag.begin(), res[v].bag.end(), res[u].bag.begin(), res[u].bag.end(), std::back_inserter(dif));
                    std::set_difference(res[u].bag.begin(), res[u].bag.end(), res[v].bag.begin(), res[v].bag.end(), std::back_inserter(dif));
                    assert(dif.size());
                    res[u].ch.erase(std::find(res[u].ch.begin(), res[u].ch.end(), v));
                    while (dif.size() > 1) {
                        const int n = res.size();
                        auto& node = res.emplace_back();
                        std::set_symmetric_difference(res[u].bag.begin(), res[u].bag.end(), std::prev(dif.end()), dif.end(), std::back_inserter(node.bag));
                        res[u].ch.push_back(n);
                        dif.pop_back();
                        node.par = u;
                        u = n;
                    }
                    res[u].ch.push_back(v);
                    res[v].par = u;
                };

                if (res[u].ch.size() == 2) {
                    for (int v : res[u].ch) if (res[u].bag != res[v].bag) {
                        const int n = res.size();
                        *std::find(res[u].ch.begin(), res[u].ch.end(), v) = n;
                        auto& node = res.emplace_back();
                        node.bag = res[u].bag;
                        node.ch = { v };
                        node.par = u;
                        fix_path(n, v);
                    }
                } else if (res[u].ch.size() == 1) {
                    fix_path(u, res[u].ch[0]);
                } else if (res[u].ch.size() == 0) {
                    while (res[u].bag.size() > 1) {
                        const int n = res.size();
                        auto& node = res.emplace_back();
                        node.bag = std::vector<int>(res[u].bag.begin(), std::prev(res[u].bag.end()));
                        node.par = u;
                        res[u].ch.push_back(n);
                        u = n;
                    }
                } else {
                    assert(false);
                }
            }
            res[root].par = -1;

            return res;
        }

        static void assert_nice(const std::vector<DecompNodeRooted>& nodes, int root) {
            auto dfs = [&](auto dfs, int u) -> void {
                for (int v : nodes[u].ch) dfs(dfs, v);
                assert(nodes[u].ch.size() <= 2);
                if (nodes[u].ch.size() == 2) {
                    int x = nodes[u].ch[0], y = nodes[u].ch[1];
                    assert(nodes[u].bag == nodes[x].bag and nodes[u].bag == nodes[y].bag);
                } else if (nodes[u].ch.size() == 1) {
                    int x = nodes[u].ch[0];
                    std::vector<int> d;
                    std::set_symmetric_difference(nodes[u].bag.begin(), nodes[u].bag.end(), nodes[x].bag.begin(), nodes[x].bag.end(), std::back_inserter(d));
                    assert(d.size() == 1);
                } else {
                    assert(nodes[u].bag.size() == 1);
                }
            };
            dfs(dfs, root);
        }
    private:
        int _n;
        std::vector<std::pair<int, int>> _edges;

        static int remove_edge(std::vector<std::vector<std::pair<int, int>>>& g, int u, int idx_uv) {
            auto [v, idx_vu] = g[u][idx_uv];

            if (idx_vu != int(g[v].size()) - 1) {
                auto [w, idx_wv] = g[v].back();
                std::swap(g[v][idx_vu], g[v].back());
                g[w][idx_wv].second = idx_vu;
            }
            g[v].pop_back();
            if (idx_uv != int(g[u].size()) - 1) {
                auto [z, idx_zu] = g[u].back();
                std::swap(g[u][idx_uv], g[u].back());
                g[z][idx_zu].second = idx_uv;
            }
            g[u].pop_back();

            remove_multiedges(g, v, idx_vu);
            remove_multiedges(g, u, idx_uv);

            return v;
        }
        static void remove_multiedges(std::vector<std::vector<std::pair<int, int>>>& g, int u, int idx_uv) {
            auto is_unnecessary = [&](int idx_uv) {
                const int du = int(g[u].size());
                if (idx_uv >= du) return false;
                if (idx_uv + 1 < du and g[u][idx_uv].first == g[u][idx_uv + 1].first) return true;
                if (idx_uv + 2 < du and g[u][idx_uv].first == g[u][idx_uv + 2].first) return true;
                if (idx_uv - 1 >= 0 and g[u][idx_uv].first == g[u][idx_uv - 1].first) return true;
                if (idx_uv - 2 >= 0 and g[u][idx_uv].first == g[u][idx_uv - 2].first) return true;
                return false;
            };
            while (is_unnecessary(idx_uv)) remove_edge(g, u, idx_uv);
        }
    };
} // namespace suisen

namespace suisen {
    enum class NodeType {
        LEAF,
        INTRODUCE,
        FORGET,
        JOIN
    };

    struct NiceDecompTree {
        static constexpr int root = 0;

        NiceDecompTree() = default;
        NiceDecompTree(std::vector<DecompNodeRooted>&& nodes) : _n(nodes.size()), _nodes(std::move(nodes)), _pst(_n, -1) {}
        NiceDecompTree(const std::vector<DecompNodeRooted>& nodes) : _n(nodes.size()), _nodes(nodes), _pst(_n, -1) {}
        NiceDecompTree(int n, const std::vector<std::pair<int, int>>& edges) : NiceDecompTree(*TreeDecompositionTW2{ n, edges }.nice_decomp()) {}
        NiceDecompTree(const std::vector<std::vector<int>>& g) : NiceDecompTree(*TreeDecompositionTW2{ g }.nice_decomp()) {}

        int size() const { return _n; }

        NodeType get_node_type(int i) const {
            if (_nodes[i].ch.size() == 0) return NodeType::LEAF;
            if (_nodes[i].ch.size() == 2) return NodeType::JOIN;
            if (_nodes[i].bag.size() > _nodes[_nodes[i].ch[0]].bag.size()) return NodeType::INTRODUCE;
            return NodeType::FORGET;
        }
        std::vector<NodeType> get_node_types() const {
            std::vector<NodeType> types(_n);
            for (int i = 0; i < _n; ++i) types[i] = get_node_type(i);
            return types;
        }

        const DecompNodeRooted& operator[](int i) const { return _nodes[i]; }
        DecompNodeRooted& operator[](int i) { return _nodes[i]; }

        template <typename T> T run_dp(
            std::function<T(const DecompNodeRooted& node, int leaf_vertex)> leaf,
            std::function<T(const DecompNodeRooted& node, const DecompNodeRooted& child_node, const T& child_result, int introduce_vertex)> introduce,
            std::function<T(const DecompNodeRooted& node, const DecompNodeRooted& child_node, const T& child_result, int forget_vertex)> forget,
            std::function<T(const DecompNodeRooted& node, const DecompNodeRooted& child_node_1, const T& child_result_1, const DecompNodeRooted& child_node_2, const T& child_result_2)> join
        ) const {
            prepare_post_order();
            std::vector<T> dp(_n);
            for (int i : _pst) {
                dp[i] = [&, this] {
                    switch (get_node_type(i)) {
                    case NodeType::LEAF:
                    {
                        return leaf(_nodes[i], _nodes[i].bag[0]);
                    }
                    case NodeType::INTRODUCE:
                    {
                        int j = _nodes[i].ch[0];
                        int sj = _nodes[j].bag.size();
                        int v = _nodes[i].bag[sj];
                        for (int k = 0; k < sj; ++k) if (_nodes[i].bag[k] != _nodes[j].bag[k]) {
                            v = _nodes[i].bag[k];
                            break;
                        }
                        return introduce(_nodes[i], _nodes[j], dp[j], v);
                    }
                    case NodeType::FORGET:
                    {
                        int j = _nodes[i].ch[0];
                        int si = _nodes[i].bag.size();
                        int v = _nodes[j].bag[si];
                        for (int k = 0; k < si; ++k) if (_nodes[i].bag[k] != _nodes[j].bag[k]) {
                            v = _nodes[j].bag[k];
                            break;
                        }
                        return forget(_nodes[i], _nodes[j], dp[j], v);
                    }
                    case NodeType::JOIN:
                    {
                        int j = _nodes[i].ch[0], k = _nodes[i].ch[1];
                        return join(_nodes[i], _nodes[j], dp[j], _nodes[k], dp[k]);
                    }
                    default:
                    {
                        assert(false);
                    }
                    }
                }();
            }
            return dp[root];
        }

    private:
        int _n;
        std::vector<DecompNodeRooted> _nodes;

        mutable std::vector<int> _pst;

        void prepare_post_order() const {
            if (_pst.empty() or _pst.front() >= 0) return;
            auto it = _pst.begin();
            std::vector<std::size_t> eid(_n, 0);
            for (int cur = root; cur >= 0;) {
                if (eid[cur] == _nodes[cur].ch.size()) {
                    *it++ = cur;
                    cur = _nodes[cur].par;
                } else {
                    cur = _nodes[cur].ch[eid[cur]++];
                }
            }
        }
    };
} // namespace suisen

using match = std::pair<int, int>;
using table_key = std::vector<match>;
using table_value = long long;
using table_entry = std::pair<table_key, table_value>;
using table = std::map<table_key, long long>;

struct state {
    static constexpr int Forgotten = -2;
    static constexpr int None = -1;
    table mp;
};

void solve() {
    using namespace suisen;

    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, m;
    std::cin >> n >> m;

    if (n == 0 and m == 0) exit(0);

    std::vector<std::set<int>> adj(n);

    std::vector<std::pair<int, int>> edges;
    for (int i = 0; i < n; ++i) {
        edges.emplace_back(i, (i + 1) % n);
    }
    for (int i = 0; i < m; ++i) {
        int u, v;
        std::cin >> u >> v;
        --u, --v;
        edges.emplace_back(u, v);
    }

    for (const auto &[u, v] : edges) {
        adj[u].insert(v);
        adj[v].insert(u);
    }

    auto leaf = [&](const DecompNodeRooted&, int leaf_vertex) -> state {
        return state { table{ table_entry{ table_key{ match{ leaf_vertex, state::None } }, table_value{ 1 } } } };
    };
    auto introduce = [&](const DecompNodeRooted&, const DecompNodeRooted&, const state& child_result, int introduce_vertex) -> state {
        table ndp;
        for (auto [matching, val] : child_result.mp) {
            {
                auto nxt_matching = matching;
                nxt_matching.emplace_back(introduce_vertex, state::None);
                std::sort(nxt_matching.begin(), nxt_matching.end());
                ndp[nxt_matching] += val;
            }
            const int k = matching.size();
            for (int i = 0; i < k; ++i) {
                auto [u, v] = matching[i];
                if (v != state::None or adj[introduce_vertex].find(u) == adj[introduce_vertex].end()) continue;
                auto nxt_matching = matching;
                nxt_matching[i].second = introduce_vertex;
                nxt_matching.emplace_back(introduce_vertex, u);
                std::sort(nxt_matching.begin(), nxt_matching.end());
                ndp[nxt_matching] += val;
            }
        }
        for (auto &[_, val] : ndp) val %= mod;
        return state { ndp };
    };
    auto forget = [&](const DecompNodeRooted&, const DecompNodeRooted&, const state& child_result, int forget_vertex) -> state {
        table ndp;
        for (auto [matching, val] : child_result.mp) {
            bool ok = true;
            table_key nxt_matching;
            for (auto [u, v] : matching) {
                if (u == forget_vertex) {
                    ok &= v != state::None;
                    continue;
                }
                if (v == forget_vertex) {
                    nxt_matching.emplace_back(u, state::Forgotten);
                } else {
                    nxt_matching.emplace_back(u, v);
                }
            }
            if (not ok) {
                continue;
            }
            std::sort(nxt_matching.begin(), nxt_matching.end());
            ndp[nxt_matching] += val;
        }
        for (auto &[_, val] : ndp) val %= mod;
        return state { ndp };
    };
    auto join = [&](const DecompNodeRooted&, const DecompNodeRooted&, const state& child_result_1, const DecompNodeRooted&, const state& child_result_2) -> state {
        table ndp;
        for (auto [matching1, val1] : child_result_1.mp) for (auto [matching2, val2] : child_result_2.mp) {
            bool ok = true;
            const int k = matching1.size();
            table_key nxt_matching;
            for (int i = 0; i < k; ++i) {
                auto [u1, v1] = matching1[i];
                auto [u2, v2] = matching2[i];
                assert(u1 == u2);
                if (v1 > v2) std::swap(v1, v2);
                if (v1 == state::Forgotten) {
                    if (v2 == state::Forgotten) {
                        ok = false;
                        break;
                    } else if (v2 == state::None) {
                        nxt_matching.emplace_back(u1, v1);
                    } else {
                        ok = false;
                        break;
                    }
                } else if (v1 == state::None) {
                    if (v2 == state::None) {
                        nxt_matching.emplace_back(u1, v1);
                    } else {
                        ok = false;
                        break;
                    }
                } else {
                    if (v1 != v2) {
                        ok = false;
                        break;
                    } else {
                        nxt_matching.emplace_back(u1, v1);
                    }
                }
                if (not ok) break;
            }
            if (ok) {
                std::sort(nxt_matching.begin(), nxt_matching.end());
                ndp[nxt_matching] += val1 * val2;
            }
        }
        for (auto &[_, val] : ndp) val %= mod;
        return state { ndp };
    };

    state dp_root = NiceDecompTree(n, edges).run_dp<state>(leaf, introduce, forget, join);

    long long ans = 0;
    for (auto [matching, val] : dp_root.mp) {
        bool ok = true;
        for (auto &[u, v] : matching) {
            if (v == state::None) {
                ok = false;
                break;
            }
        }
        if (ok) {
            ans += val;
        }
    }

    std::cout << ans % mod << std::endl;
}

int main() {
    while (true) solve();
}
accuracy: 1
time_ms: 1200
memory_kb: 103696
final_rank: 20

code_snippet: //#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 1000003;;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-12;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 2;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}




int n, m;
void solve() {
	vector<P> vp;
	vp.push_back({ 0,n - 1 });
	rep(i, m) {
		int l, r; cin >> l >> r; l--; r--;
		if (l > r)swap(l, r);
		vp.push_back({ l,r });
	}
	auto comp = [&](P a, P b) {
		return a.first != b.first ? a.first < b.first : a.second > b.second;
	};
	sort(all(vp), comp);
	vector<vector<int>> G(vp.size());
	vector<int> ind;
	rep(i, vp.size()) {
		while (ind.size() && vp[ind.back()].second <= vp[i].first)ind.pop_back();
		if (ind.size()) {
			//cout << "? " << ind.back() << " " << i << "\n";
			G[ind.back()].push_back(i);
		}
		ind.push_back(i);
	}
	//cout << G[0].size() << "\n";
	using ar = array<modint, 4>;
	function<ar(int)> dfs = [&](int id)->ar {
		int l = vp[id].first;
		int r = vp[id].second;
		ar res;
		if (G[id].empty()) {
			if ((l + r) % 2) {
				res = { 1,0,0,1 };
			}
			else {
				res = { 0,1,1,0 };
			}
		}
		else {
			rep(i, G[id].size()) {
				int to = G[id][i];
				ar nex = dfs(to);
				if (i == 0) {
					res = nex;
					//cout << "! " << id << " " <<to<<" "<< vp[to].first << " " << l << "\n";
					if ((vp[to].first + l) % 2) {
						swap(res[0], res[1]);
						swap(res[2], res[3]);
					}
				}
				else {
					ar ndp; rep(j, 4)ndp[j] = 0;
					rep(j, 4) {
						rep(k, 4) {
							int c = vp[to].first - vp[G[id][i - 1]].second + 1;
							c %= 2;
							if (j & 2)c ^= 1;
							if (k & 1)c ^= 1;
							if (c)continue;
							int nj = 0;
							if (j & 1)nj |= 1;
							if (k & 2)nj |= 2;
							ndp[nj] += res[j]*nex[k];
						}
					}
					swap(res, ndp);
				}
			}
			int las = vp[G[id].back()].second;
			if((r + las) % 2) {
				swap(res[0], res[2]);
				swap(res[1], res[3]);
			}
		}
		res[3] += res[0];
		//cout << "? " << id;
		//rep(j, 4)cout << " " << res[j];
		//cout << "\n";
		return res;
	};
	ar a = dfs(0);
	cout << a[3] << "\n";
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(8);
	//init_f();
	//init();
	//int t; cin >> t; rep(i, t)
	while(cin>>n>>m,n)
	solve();
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 12640
final_rank: 5

code_snippet: #line 1 "/Users/nok0/Documents/Programming/nok0/cftemp.hpp"
#include <bits/stdc++.h>
using namespace std;

#pragma region Macros
// rep macro
#define foa(v, a) for(auto &v : a)
#define REPname(a, b, c, d, e, ...) e
#define REP(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int i = 0; i < (x); ++i)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define REPSname(a, b, c, ...) c
#define REPS(...) REPSname(__VA_ARGS__, REPS1, REPS0)(__VA_ARGS__)
#define REPS0(x) for(int i = 1; i <= (x); ++i)
#define REPS1(i, x) for(int i = 1; i <= (x); ++i)
#define RREPname(a, b, c, d, e, ...) e
#define RREP(...) RREPname(__VA_ARGS__, RREP3, RREP2, RREP1, RREP0)(__VA_ARGS__)
#define RREP0(x) for(int i = (x)-1; i >= 0; --i)
#define RREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define RREP2(i, r, l) for(int i = (r)-1; i >= (l); --i)
#define RREP3(i, r, l, c) for(int i = (r)-1; i >= (l); i -= (c))
#define RREPSname(a, b, c, ...) c
#define RREPS(...) RREPSname(__VA_ARGS__, RREPS1, RREPS0)(__VA_ARGS__)
#define RREPS0(x) for(int i = (x); i >= 1; --i)
#define RREPS1(i, x) for(int i = (x); i >= 1; --i)

// name macro
#define pb push_back
#define eb emplace_back
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define popcnt(x) __builtin_popcountll(x)
template <class T = int>
using V = std::vector<T>;
template <class T = int>
using VV = std::vector<std::vector<T>>;
template <class T>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
using ll = long long;
using ld = long double;
using int128 = __int128_t;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;

// input macro
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
	is >> p.first >> p.second;
	return is;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
	for(T &i : v) is >> i;
	return is;
}
std::istream &operator>>(std::istream &is, __int128_t &a) {
	std::string s;
	is >> s;
	__int128_t ret = 0;
	for(int i = 0; i < s.length(); i++)
		if('0' <= s[i] and s[i] <= '9')
			ret = 10 * ret + s[i] - '0';
	a = ret * (s[0] == '-' ? -1 : 1);
	return is;
}
namespace scanner {
void scan(int &a) { std::cin >> a; }
void scan(long long &a) { std::cin >> a; }
void scan(std::string &a) { std::cin >> a; }
void scan(char &a) { std::cin >> a; }
void scan(char a[]) { std::scanf("%s", a); }
void scan(double &a) { std::cin >> a; }
void scan(long double &a) { std::cin >> a; }
template <class T, class U>
void scan(std::pair<T, U> &p) { std::cin >> p; }
template <class T>
void scan(std::vector<T> &a) { std::cin >> a; }
void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#define VEC(type, name, size)     \
	std::vector<type> name(size); \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                                    \
	std::vector<std::vector<type>> name(h, std::vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)             \
	std::string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHAR(...)     \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DOUBLE(...)     \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)

// output-macro
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &a) {
	for(int i = 0; i < int(a.size()); ++i) {
		if(i) os << " ";
		os << a[i];
	}
	return os;
}
std::ostream &operator<<(std::ostream &dest, __int128_t &value) {
	std::ostream::sentry s(dest);
	if(s) {
		__uint128_t tmp = value < 0 ? -value : value;
		char buffer[128];
		char *d = std::end(buffer);
		do {
			--d;
			*d = "0123456789"[tmp % 10];
			tmp /= 10;
		} while(tmp != 0);
		if(value < 0) {
			--d;
			*d = '-';
		}
		int len = std::end(buffer) - d;
		if(dest.rdbuf()->sputn(d, len) != len) {
			dest.setstate(std::ios_base::badbit);
		}
	}
	return dest;
}
template <class T>
void print(const T a) { std::cout << a << '\n'; }
template <class Head, class... Tail>
void print(Head H, Tail... T) {
	std::cout << H << ' ';
	print(T...);
}
template <class T>
void printel(const T a) { std::cout << a << '\n'; }
template <class T>
void printel(const std::vector<T> &a) {
	for(const auto &v : a)
		std::cout << v << '\n';
}
template <class Head, class... Tail>
void printel(Head H, Tail... T) {
	std::cout << H << '\n';
	printel(T...);
}
void Yes(const bool b = true) { std::cout << (b ? "Yes\n" : "No\n"); }
void No() { std::cout << "No\n"; }
void YES(const bool b = true) { std::cout << (b ? "YES\n" : "NO\n"); }
void NO() { std::cout << "NO\n"; }
void err(const bool b = true) {
	if(b) {
		std::cout << "-1\n", exit(0);
	}
}

//debug macro
namespace debugger {
template <class T>
void view(const std::vector<T> &a) {
	std::cerr << "{ ";
	for(const auto &v : a) {
		std::cerr << v << ", ";
	}
	std::cerr << "\b\b }";
}
template <class T>
void view(const std::vector<std::vector<T>> &a) {
	std::cerr << "{\n";
	for(const auto &v : a) {
		std::cerr << "\t";
		view(v);
		std::cerr << "\n";
	}
	std::cerr << "}";
}
template <class T, class U>
void view(const std::vector<std::pair<T, U>> &a) {
	std::cerr << "{\n";
	for(const auto &p : a) std::cerr << "\t(" << p.first << ", " << p.second << ")\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &p : m) std::cerr << "\t[" << p.first << "] : " << p.second << "\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::pair<T, U> &p) { std::cerr << "(" << p.first << ", " << p.second << ")"; }
template <class T>
void view(const std::set<T> &s) {
	std::cerr << "{ ";
	for(auto &v : s) {
		view(v);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <class T>
void view(const T &e) { std::cerr << e; }
}  // namespace debugger
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	debugger::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(false)
#else
#define debug(...) (void(0))
#endif

// vector macro
template <class T>
int lb(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::lower_bound((a).begin(), (a).end(), (x))); }
template <class T>
int ub(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::upper_bound((a).begin(), (a).end(), (x))); }
template <class T>
void UNIQUE(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<T> press(std::vector<T> &a) {
	auto res = a;
	UNIQUE(res);
	for(auto &v : a)
		v = lb(res, v);
	return res;
}
#define SORTname(a, b, c, ...) c
#define SORT(...) SORTname(__VA_ARGS__, SORT1, SORT0, ...)(__VA_ARGS__)
#define SORT0(a) std::sort((a).begin(), (a).end())
#define SORT1(a, c) std::sort((a).begin(), (a).end(), [](const auto x, const auto y) { return x c y; })
template <class T>
void ADD(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v += x;
}
template <class T>
void SUB(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v -= x;
}
std::vector<std::pair<char, int>> rle(const string &s) {
	int n = s.size();
	std::vector<std::pair<char, int>> ret;
	for(int l = 0; l < n;) {
		int r = l + 1;
		for(; r < n and s[l] == s[r]; r++) {}
		ret.emplace_back(s[l], r - l);
		l = r;
	}
	return ret;
}
template <class T>
std::vector<std::pair<T, int>> rle(const std::vector<T> &v) {
	int n = v.size();
	std::vector<std::pair<T, int>> ret;
	for(int l = 0; l < n;) {
		int r = l + 1;
		for(; r < n and v[l] == v[r]; r++) {}
		ret.emplace_back(v[l], r - l);
		l = r;
	}
	return ret;
}
std::vector<int> iota(int n) {
	std::vector<int> p(n);
	std::iota(p.begin(), p.end(), 0);
	return p;
}
template <class T>
struct cum_vector {
public:
	cum_vector() = default;
	template <class U>
	cum_vector(const std::vector<U> &vec) : cum((int)vec.size() + 1) {
		for(int i = 0; i < (int)vec.size(); i++)
			cum[i + 1] = cum[i] + vec[i];
	}
	T prod(int l, int r) {
		return cum[r] - cum[l];
	}

private:
	std::vector<T> cum;
};

// math macro
template <class T, class U>
inline bool chmin(T &a, const U &b) { return a > b ? a = b, true : false; }
template <class T, class U>
inline bool chmax(T &a, const U &b) { return a < b ? a = b, true : false; }
template <class T>
T divup(T x, T y) { return (x + y - 1) / y; }
template <class T>
T POW(T a, long long n) {
	T ret = 1;
	while(n) {
		if(n & 1) ret *= a;
		a *= a;
		n >>= 1;
	}
	return ret;
}
// modpow
long long POW(long long a, long long n, const int mod) {
	long long ret = 1;
	a = (a % mod + mod) % mod;
	while(n) {
		if(n & 1) (ret *= a) %= mod;
		(a *= a) %= mod;
		n >>= 1;
	}
	return ret;
}
template <class T, class F>
T bin_search(T ok, T ng, const F &f) {
	while(abs(ok - ng) > 1) {
		T mid = (ok + ng) >> 1;
		(f(mid) ? ok : ng) = mid;
	}
	return ok;
}
template <class T, class F>
T bin_search(T ok, T ng, const F &f, int loop) {
	for(int i = 0; i < loop; i++) {
		T mid = (ok + ng) >> 1;
		(f(mid) ? ok : ng) = mid;
	}
	return ok;
}

// others
struct fast_io {
	fast_io() {
		ios::sync_with_stdio(false);
		cin.tie(nullptr);
		cout << fixed << setprecision(15);
	}
} fast_io_;
const int inf = 1e9;
const ll INF = 1e18;
#pragma endregion

void main_();

int main() {
	main_();
	return 0;
}
#line 1 "/Users/nok0/Documents/Programming/nok0/atcoder/modint.hpp"



#line 6 "/Users/nok0/Documents/Programming/nok0/atcoder/modint.hpp"
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

#line 1 "/Users/nok0/Documents/Programming/nok0/atcoder/internal_math.hpp"



#line 5 "/Users/nok0/Documents/Programming/nok0/atcoder/internal_math.hpp"

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m < 2^31`
    explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

// @param n `n < 2^32`
// @param m `1 <= m < 2^32`
// @return sum_{i=0}^{n-1} floor((ai + b) / m) (mod 2^64)
unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
    unsigned long long ans = 0;
    while (true) {
        if (a >= m) {
            ans += n * (n - 1) / 2 * (a / m);
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        unsigned long long y_max = a * n + b;
        if (y_max < m) break;
        // y_max < m * (n + 1)
        // floor(y_max / m) <= n
        n = (unsigned long long)(y_max / m);
        b = (unsigned long long)(y_max % m);
        std::swap(m, a);
    }
    return ans;
}

}  // namespace internal

}  // namespace atcoder


#line 1 "/Users/nok0/Documents/Programming/nok0/atcoder/internal_type_traits.hpp"



#line 7 "/Users/nok0/Documents/Programming/nok0/atcoder/internal_type_traits.hpp"

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder


#line 14 "/Users/nok0/Documents/Programming/nok0/atcoder/modint.hpp"

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder


#line 4 "/Users/nok0/Documents/Programming/nok0/math/factorial.hpp"

#line 6 "/Users/nok0/Documents/Programming/nok0/math/factorial.hpp"

template <class T>
struct factorial {
public:
	static int MAX;
	static std::vector<T> fac, finv, inv;

	factorial() {}

	T binom(int n, int r) {
		if(n < r or n < 0 or r < 0) return T(0);
		assert(n < MAX);
		return fac[n] * finv[r] * finv[n - r];
	}

	T large_binom(int n, int r) {
		if(n < r or n < 0 or r < 0) return T(0);
		assert(r < MAX);
		T ret = finv[r];
		for(int i = 1; i <= r; ++i)
			ret *= (n + 1 - i);
		return ret;
	}

	static void set_size(int n = 3000000) {
		MAX = (n > 1 ? n : 1) + 1;
		if((int)fac.size() >= MAX) return;
		fac.resize(MAX);
		finv.resize(MAX);
		inv.resize(MAX);
		const int MOD = T::mod();
		fac[0] = fac[1] = 1;
		finv[0] = finv[1] = 1;
		inv[1] = 1;
		for(int i = 2; i < MAX; i++) {
			fac[i] = fac[i - 1] * i;
			inv[i] = (T)MOD - inv[MOD % i] * (MOD / i);
			finv[i] = finv[i - 1] * inv[i];
		}
	}
};
template <class T>
int factorial<T>::MAX = 0;
template <class T>
std::vector<T> factorial<T>::fac;
template <class T>
std::vector<T> factorial<T>::finv;
template <class T>
std::vector<T> factorial<T>::inv;
#line 2 "/Users/nok0/Documents/Programming/nok0/math/modint_iostream.hpp"

#line 4 "/Users/nok0/Documents/Programming/nok0/math/modint_iostream.hpp"
template <int m>
std::istream &std::operator>>(std::istream &is, atcoder::static_modint<m> &a) {
	long long v;
	is >> v;
	a = v;
	return is;
}
template <int m>
std::istream &std::operator>>(std::istream &is, atcoder::dynamic_modint<m> &a) {
	long long v;
	is >> v;
	a = v;
	return is;
}
template <int m>
std::ostream &std::operator<<(std::ostream &os, const atcoder::static_modint<m> &a) { return os << a.val(); }
template <int m>
std::ostream &std::operator<<(std::ostream &os, const atcoder::dynamic_modint<m> &a) { return os << a.val(); }
#line 3 "f.cpp"

using mint = atcoder::static_modint<1000003>;

void main_() {
	while(1) {
		INT(n, m);
		if(n & 1) {
			print(0);
			continue;
		}
		V<pii> uv(m);
		if(!n) break;
		auto f_hash = [n](int l, int r) {
			return (ll)l * n + r;
		};
		unordered_set<ll> es;
		vector<vector<int>> valid(n);
		REP(i, n - 1) {
			valid[i].pb(i + 1);
		}
		REP(i, m) {
			INT(u, v);
			--u, --v;
			if(u > v) swap(u, v);
			es.insert(f_hash(u, v));
			uv[i] = {u, v};
			if((v - u) & 1) {
				valid[u].pb(v);
				valid[v].pb(u);
			}
		}
		REP(i, n) {
			SORT(valid[i]);
		}
		auto dp = [&](auto dp, int l, int r) -> mint {
			if(l + 1 == r) return 1;
			ll h = f_hash(l, r);
			mint ret = 0;
			if(es.count(h)) ret += dp(dp, l + 1, r - 1);
			int x = lb(valid[l], r) - 1;
			if(x >= 0 and x < SZ(valid[l]) and valid[l][x] >= l) {
				ret += dp(dp, l, valid[l][x]) * dp(dp, valid[l][x] + 1, r);
			}
			return ret;
		};
		mint res = 0;
		res += dp(dp, 1, n - 2);
		if(SZ(valid[0])) {
			int x = valid[0].back();
			if(x != n - 1) {
				res += dp(dp, 0, x) * dp(dp, x + 1, n - 1);
			}
		}
		print(res);
	}
}
accuracy: 1
time_ms: 6970
memory_kb: 11384
final_rank: 19

code_snippet: #line 1 "other/sister.cpp"
// #undef _GLIBCXX_DEBUG
// #define NDEBUG
#include <bits/extc++.h>

#line 2 "Library/lib/alias"

/**
 * @file alias
 * @brief Alias
 */

#line 13 "Library/lib/alias"

#line 2 "Library/lib/bit"

#if __cplusplus > 201703L

#include <bit>

#else

#ifndef _GLIBCXX_BIT
#define _GLIBCXX_BIT 1

#include <limits>
#include <type_traits>

namespace std {

template <typename _Tp> constexpr int __countl_zero(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;

  if (__x == 0) return _Nd;

  constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
  constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
  constexpr auto _Nd_u = numeric_limits<unsigned>::digits;

  if
    _GLIBCXX17_CONSTEXPR(_Nd <= _Nd_u) {
      constexpr int __diff = _Nd_u - _Nd;
      return __builtin_clz(__x) - __diff;
    }
  else if
    _GLIBCXX17_CONSTEXPR(_Nd <= _Nd_ul) {
      constexpr int __diff = _Nd_ul - _Nd;
      return __builtin_clzl(__x) - __diff;
    }
  else if
    _GLIBCXX17_CONSTEXPR(_Nd <= _Nd_ull) {
      constexpr int __diff = _Nd_ull - _Nd;
      return __builtin_clzll(__x) - __diff;
    }
  else  // (_Nd > _Nd_ull)
  {
    static_assert(_Nd <= (2 * _Nd_ull),
                  "Maximum supported integer size is 128-bit");

    unsigned long long __high = __x >> _Nd_ull;
    if (__high != 0) {
      constexpr int __diff = (2 * _Nd_ull) - _Nd;
      return __builtin_clzll(__high) - __diff;
    }
    constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
    unsigned long long __low = __x & __max_ull;
    return (_Nd - _Nd_ull) + __builtin_clzll(__low);
  }
}

template <typename _Tp> constexpr int __countr_zero(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;

  if (__x == 0) return _Nd;

  constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
  constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
  constexpr auto _Nd_u = numeric_limits<unsigned>::digits;

  if
    _GLIBCXX17_CONSTEXPR(_Nd <= _Nd_u)
  return __builtin_ctz(__x);
  else if _GLIBCXX17_CONSTEXPR(_Nd <= _Nd_ul) return __builtin_ctzl(__x);
  else if _GLIBCXX17_CONSTEXPR(_Nd <= _Nd_ull) return __builtin_ctzll(__x);
  else  // (_Nd > _Nd_ull)
  {
    static_assert(_Nd <= (2 * _Nd_ull),
                  "Maximum supported integer size is 128-bit");

    constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
    unsigned long long __low = __x & __max_ull;
    if (__low != 0) return __builtin_ctzll(__low);
    unsigned long long __high = __x >> _Nd_ull;
    return __builtin_ctzll(__high) + _Nd_ull;
  }
}

template <typename _Tp> constexpr int __popcount(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;

  if (__x == 0) return 0;

  constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
  constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
  constexpr auto _Nd_u = numeric_limits<unsigned>::digits;

  if
    _GLIBCXX17_CONSTEXPR(_Nd <= _Nd_u)
  return __builtin_popcount(__x);
  else if _GLIBCXX17_CONSTEXPR(_Nd <= _Nd_ul) return __builtin_popcountl(__x);
  else if _GLIBCXX17_CONSTEXPR(_Nd <= _Nd_ull) return __builtin_popcountll(__x);
  else  // (_Nd > _Nd_ull)
  {
    static_assert(_Nd <= (2 * _Nd_ull),
                  "Maximum supported integer size is 128-bit");

    constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
    unsigned long long __low = __x & __max_ull;
    unsigned long long __high = __x >> _Nd_ull;
    return __builtin_popcountll(__low) + __builtin_popcountll(__high);
  }
}

template <typename _Tp> constexpr _Tp __bit_ceil(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  if (__x == 0 || __x == 1) return 1;
  auto __shift_exponent = _Nd - __countl_zero((_Tp)(__x - 1u));
#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
  if (!__builtin_is_constant_evaluated()) {
    __glibcxx_assert(__shift_exponent != numeric_limits<_Tp>::digits);
  }
#endif
  using __promoted_type = decltype(__x << 1);
  if
    _GLIBCXX17_CONSTEXPR(!is_same<__promoted_type, _Tp>::value) {
      const int __extra_exp = sizeof(__promoted_type) / sizeof(_Tp) / 2;
      __shift_exponent |= (__shift_exponent & _Nd) << __extra_exp;
    }
  return (_Tp)1u << __shift_exponent;
}

template <typename _Tp> constexpr _Tp __bit_floor(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  if (__x == 0) return 0;
  return (_Tp)1u << (_Nd - __countl_zero((_Tp)(__x >> 1)));
}

template <typename _Tp> constexpr _Tp __bit_width(_Tp __x) noexcept {
  constexpr auto _Nd = numeric_limits<_Tp>::digits;
  return _Nd - __countl_zero(__x);
}

}  // namespace std

#endif

#endif
#line 2 "Library/lib/limits"

#line 4 "Library/lib/limits"

namespace workspace {

template <class _Tp> struct numeric_limits : std::numeric_limits<_Tp> {};

#ifdef __SIZEOF_INT128__

template <> struct numeric_limits<__uint128_t> {
  constexpr static __uint128_t max() { return ~__uint128_t(0); }
  constexpr static __uint128_t min() { return 0; }
};

template <> struct numeric_limits<__int128_t> {
  constexpr static __int128_t max() {
    return numeric_limits<__uint128_t>::max() >> 1;
  }
  constexpr static __int128_t min() { return -max() - 1; }
};

#endif

}  // namespace workspace
#line 16 "Library/lib/alias"

namespace workspace {

constexpr char eol = '\n';

using namespace std;

using i32 = int_least32_t;
using u32 = uint_least32_t;
using i64 = int_least64_t;
using u64 = uint_least64_t;

#ifdef __SIZEOF_INT128__
using i128 = __int128_t;
using u128 = __uint128_t;
#else
#warning 128bit integer is not available.
#endif

namespace _alias_impl {

template <class> struct first_arg { using type = void; };

template <class _Tp, class = void> struct parse_comp : first_arg<_Tp> {};

template <class _Tp>
struct parse_comp<_Tp, std::__void_t<decltype(&_Tp::operator())>>
    : first_arg<decltype(&_Tp::operator())> {};

template <class _R, class _Tp, class... _Args>
struct first_arg<_R(_Tp, _Args...)> {
  using type = _Tp;
};

template <class _R, class _Tp, class... _Args>
struct first_arg<_R (*)(_Tp, _Args...)> {
  using type = _Tp;
};

template <class _G, class _R, class _Tp, class... _Args>
struct first_arg<_R (_G::*)(_Tp, _Args...)> {
  using type = _Tp;
};

template <class _G, class _R, class _Tp, class... _Args>
struct first_arg<_R (_G::*)(_Tp, _Args...) const> {
  using type = _Tp;
};

}  // namespace _alias_impl

template <class _Tp = void, class _Compare = std::less<_Tp>>
decltype(auto) make_priority_queue(_Compare __x = _Compare()) noexcept {
  using type = std::conditional_t<
      std::is_void<_Tp>::value,
      std::decay_t<typename _alias_impl::parse_comp<_Compare>::type>, _Tp>;

  return std::priority_queue<type, std::vector<type>, _Compare>(__x);
}

template <class _Tp = void, class _Compare = std::less<_Tp>>
decltype(auto) make_set(_Compare __x = _Compare()) noexcept {
  using type = std::conditional_t<
      std::is_void<_Tp>::value,
      std::decay_t<typename _alias_impl::parse_comp<_Compare>::type>, _Tp>;

  return std::set<type, _Compare>(__x);
}

template <class _Key, class _Mapped, class _Compare = std::less<_Key>>
decltype(auto) make_map(_Compare __x = _Compare()) noexcept {
  return std::map<_Key, _Mapped, _Compare>(__x);
}

template <class _T1, class _T2,
          typename = decltype(std::declval<const _T2 &>() <
                              std::declval<const _T1 &>())>
constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    min(const _T1 &__x, const _T2 &__y) noexcept {
  return __y < __x ? __y : __x;
}

template <class _T1, class _T2, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _T2 &>(), std::declval<const _T1 &>()))>
constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    min(const _T1 &__x, const _T2 &__y, _Compare __comp) noexcept {
  return __comp(__y, __x) ? __y : __x;
}

template <class _Tp, typename = decltype(std::declval<const _Tp &>() <
                                         std::declval<const _Tp &>())>
constexpr _Tp min(std::initializer_list<_Tp> __x) noexcept {
  return *std::min_element(__x.begin(), __x.end());
}

template <class _Tp, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _Tp &>(), std::declval<const _Tp &>()))>
constexpr _Tp min(std::initializer_list<_Tp> __x, _Compare __comp) noexcept {
  return *std::min_element(__x.begin(), __x.end(), __comp);
}

template <class _T1, class _T2,
          typename = decltype(std::declval<const _T1 &>() <
                              std::declval<const _T2 &>())>

constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    max(const _T1 &__x, const _T2 &__y) noexcept {
  return __x < __y ? __y : __x;
}

template <class _T1, class _T2, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _T1 &>(), std::declval<const _T2 &>()))>
constexpr
    typename std::conditional<std::is_same<_T1, _T2>::value, const _T1 &,
                              typename std::common_type<_T1, _T2>::type>::type
    max(const _T1 &__x, const _T2 &__y, _Compare __comp) noexcept {
  return __comp(__x, __y) ? __y : __x;
}

template <class _Tp, typename = decltype(std::declval<const _Tp &>() <
                                         std::declval<const _Tp &>())>
constexpr _Tp max(std::initializer_list<_Tp> __x) noexcept {
  return *std::max_element(__x.begin(), __x.end());
}

template <class _Tp, class _Compare,
          typename = decltype(std::declval<_Compare>()(
              std::declval<const _Tp &>(), std::declval<const _Tp &>()))>
constexpr _Tp max(std::initializer_list<_Tp> __x, _Compare __comp) noexcept {
  return *std::max_element(__x.begin(), __x.end(), __comp);
}

template <typename _Tp> constexpr _Tp __bsf(_Tp __x) noexcept {
  return std::__countr_zero(__x);
}

template <typename _Tp> constexpr _Tp __bsr(_Tp __x) noexcept {
  return std::__bit_width(__x) - 1;
}

}  // namespace workspace
#line 2 "Library/src/modular/modint.hpp"

/**
 * @file modint.hpp
 *
 * @brief Modular Arithmetic
 */

#line 12 "Library/src/modular/modint.hpp"

#line 2 "Library/src/number_theory/sqrt_mod.hpp"

/**
 * @file sqrt_mod.hpp
 * @brief Tonelli-Shanks Algorithm
 */

#line 2 "Library/src/number_theory/pow_mod.hpp"

/**
 * @file mod_pow.hpp
 * @brief Modular Exponentiation
 */

#line 9 "Library/src/number_theory/pow_mod.hpp"

#line 2 "Library/src/utils/sfinae.hpp"

/**
 * @file sfinae.hpp
 * @brief SFINAE
 */

#line 10 "Library/src/utils/sfinae.hpp"
#include <type_traits>

#ifndef __INT128_DEFINED__

#ifdef __SIZEOF_INT128__
#define __INT128_DEFINED__ 1
#else
#define __INT128_DEFINED__ 0
#endif

#endif

namespace std {

#if __INT128_DEFINED__

template <> struct make_signed<__uint128_t> { using type = __int128_t; };
template <> struct make_signed<__int128_t> { using type = __int128_t; };

template <> struct make_unsigned<__uint128_t> { using type = __uint128_t; };
template <> struct make_unsigned<__int128_t> { using type = __uint128_t; };

template <> struct is_signed<__uint128_t> : std::false_type {};
template <> struct is_signed<__int128_t> : std::true_type {};

template <> struct is_unsigned<__uint128_t> : std::true_type {};
template <> struct is_unsigned<__int128_t> : std::false_type {};

#endif

}  // namespace std

namespace workspace {

template <class Tp, class... Args> struct variadic_front { using type = Tp; };

template <class... Args> struct variadic_back;

template <class Tp> struct variadic_back<Tp> { using type = Tp; };

template <class Tp, class... Args> struct variadic_back<Tp, Args...> {
  using type = typename variadic_back<Args...>::type;
};

template <class type, template <class> class trait>
using enable_if_trait_type = typename std::enable_if<trait<type>::value>::type;

/**
 * @brief Return type of subscripting ( @c [] ) access.
 */
template <class _Tp>
using subscripted_type =
    typename std::decay<decltype(std::declval<_Tp&>()[0])>::type;

template <class Container>
using element_type = typename std::decay<decltype(
    *std::begin(std::declval<Container&>()))>::type;

template <class _Tp, class = std::nullptr_t>
struct has_begin : std::false_type {};

template <class _Tp>
struct has_begin<_Tp, decltype(std::begin(std::declval<_Tp>()), nullptr)>
    : std::true_type {};

template <class _Tp, class = std::nullptr_t>
struct has_mod : std::false_type {};

template <class _Tp>
struct has_mod<_Tp, decltype(_Tp::mod, nullptr)> : std::true_type {};

template <class _Tp, class = void> struct is_integral_ext : std::false_type {};
template <class _Tp>
struct is_integral_ext<
    _Tp, typename std::enable_if<std::is_integral<_Tp>::value>::type>
    : std::true_type {};

#if __INT128_DEFINED__

template <> struct is_integral_ext<__int128_t> : std::true_type {};
template <> struct is_integral_ext<__uint128_t> : std::true_type {};

#endif

#if __cplusplus >= 201402

template <class _Tp>
constexpr static bool is_integral_ext_v = is_integral_ext<_Tp>::value;

#endif

template <typename _Tp, typename = void> struct multiplicable_uint {
  using type = uint_least32_t;
};
template <typename _Tp>
struct multiplicable_uint<
    _Tp,
    typename std::enable_if<(2 < sizeof(_Tp)) &&
                            (!__INT128_DEFINED__ || sizeof(_Tp) <= 4)>::type> {
  using type = uint_least64_t;
};

#if __INT128_DEFINED__

template <typename _Tp>
struct multiplicable_uint<_Tp,
                          typename std::enable_if<(4 < sizeof(_Tp))>::type> {
  using type = __uint128_t;
};

#endif

template <typename _Tp> struct multiplicable_int {
  using type =
      typename std::make_signed<typename multiplicable_uint<_Tp>::type>::type;
};

template <typename _Tp> struct multiplicable {
  using type = std::conditional_t<
      is_integral_ext<_Tp>::value,
      std::conditional_t<std::is_signed<_Tp>::value,
                         typename multiplicable_int<_Tp>::type,
                         typename multiplicable_uint<_Tp>::type>,
      _Tp>;
};

}  // namespace workspace
#line 11 "Library/src/number_theory/pow_mod.hpp"

namespace workspace {

/**
 * @brief Compile time modular exponentiation.
 *
 * @param __x
 * @param __n Exponent
 * @param __mod Modulus
 * @return
 */
template <class _Tp>
constexpr std::enable_if_t<(is_integral_ext<_Tp>::value), _Tp> pow_mod(
    _Tp __x, _Tp __n, _Tp __mod) noexcept {
  assert(__mod > 0);

  using mul_type = typename multiplicable_uint<_Tp>::type;

  if ((__x %= __mod) < 0) __x += __mod;

  mul_type __y{1};

  while (__n) {
    if (__n & 1) (__y *= __x) %= __mod;
    __x = (mul_type)__x * __x % __mod;
    __n >>= 1;
  }

  return __y;
};

}  // namespace workspace
#line 10 "Library/src/number_theory/sqrt_mod.hpp"

namespace workspace {

/**
 * @brief Compile time modular square root.
 *
 * @param __x
 * @param __mod Modulus
 * @return One if it exists. Otherwise -1.
 */
template <class _Tp>
constexpr std::enable_if_t<(is_integral_ext<_Tp>::value), _Tp> sqrt_mod(
    _Tp __x, _Tp __mod) noexcept {
  assert(__mod > 0);

  using mul_type = typename multiplicable_uint<_Tp>::type;

  if ((__x %= __mod) < 0) __x += __mod;

  if (!__x) return 0;

  if (__mod == 2) return __x;

  if (pow_mod(__x, __mod >> 1, __mod) != 1) return -1;

  _Tp __z = __builtin_ctz(__mod - 1), __q = __mod >> __z;

  mul_type __a = pow_mod(__x, (__q + 1) >> 1, __mod), __b = 2;
  while (pow_mod<_Tp>(__b, __mod >> 1, __mod) == 1) ++__b;
  __b = pow_mod<_Tp>(__b, __q, __mod);

  _Tp __shift = 0;

  for (auto __r = __a * __a % __mod * pow_mod(__x, __mod - 2, __mod) % __mod;
       __r != 1; (__r *= (__b *= __b) %= __mod) %= __mod) {
    auto __bsf = __z;

    for (auto __e = __r; __e != 1; --__bsf) (__e *= __e) %= __mod;

    while (++__shift != __bsf) (__b *= __b) %= __mod;

    (__a *= __b) %= __mod;
  }

  return __a;
};

}  // namespace workspace
#line 15 "Library/src/modular/modint.hpp"

namespace workspace {

namespace _modint_impl {

template <auto _Mod, unsigned _Storage> struct modint {
  static_assert(is_integral_ext<decltype(_Mod)>::value,
                "_Mod must be integral type.");

  using mod_type = std::make_signed_t<typename std::conditional<
      0 < _Mod, std::add_const_t<decltype(_Mod)>, decltype(_Mod)>::type>;

  using value_type = std::decay_t<mod_type>;

  using mul_type = typename multiplicable_uint<value_type>::type;

  // Modulus
  static mod_type mod;

  static unsigned storage;

 private:
  value_type value = 0;

  struct direct_ctor_t {};
  constexpr static direct_ctor_t direct_ctor_tag{};

  // Direct constructor
  template <class _Tp>
  constexpr modint(_Tp __n, direct_ctor_t) noexcept : value(__n) {}

 public:
  constexpr modint() noexcept = default;

  template <class _Tp, typename = std::enable_if_t<is_integral_ext<_Tp>::value>>
  constexpr modint(_Tp __n) noexcept
      : value((__n %= mod) < 0 ? __n += mod : __n) {}

  constexpr modint(bool __n) noexcept : value(__n) {}

  constexpr operator value_type() const noexcept { return value; }

  // unary operators {{
  constexpr modint operator++(int) noexcept {
    modint __t{*this};
    operator++();
    return __t;
  }

  constexpr modint operator--(int) noexcept {
    modint __t{*this};
    operator--();
    return __t;
  }

  constexpr modint &operator++() noexcept {
    if (++value == mod) value = 0;
    return *this;
  }

  constexpr modint &operator--() noexcept {
    if (!value)
      value = mod - 1;
    else
      --value;
    return *this;
  }

  constexpr modint operator+() const noexcept { return *this; }

  constexpr modint operator-() const noexcept {
    return {value ? mod - value : 0, direct_ctor_tag};
  }

  // }} unary operators

  // operator+= {{

  constexpr modint &operator+=(const modint &__x) noexcept {
    if ((value += __x.value) >= mod) value -= mod;
    return *this;
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type &
  operator+=(_Tp const &__x) noexcept {
    if (((value += __x) %= mod) < 0) value += mod;
    return *this;
  }

  // }} operator+=

  // operator+ {{

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
  operator+(_Tp const &__x) const noexcept {
    return modint{*this} += __x;
  }

  constexpr modint operator+(modint __x) const noexcept { return __x += *this; }

  template <class _Tp>
  constexpr friend
      typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
      operator+(_Tp const &__x, modint __y) noexcept {
    return __y += __x;
  }

  // }} operator+

  // operator-= {{

  constexpr modint &operator-=(const modint &__x) noexcept {
    if ((value -= __x.value) < 0) value += mod;
    return *this;
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type &
  operator-=(_Tp __x) noexcept {
    if (((value -= __x) %= mod) < 0) value += mod;
    return *this;
  }

  // }} operator-=

  // operator- {{

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
  operator-(_Tp const &__x) const noexcept {
    return modint{*this} -= __x;
  }

  constexpr modint operator-(const modint &__x) const noexcept {
    return modint{*this} -= __x;
  }

  template <class _Tp>
  constexpr friend
      typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
      operator-(_Tp __x, const modint &__y) noexcept {
    if (((__x -= __y.value) %= mod) < 0) __x += mod;
    return {__x, direct_ctor_tag};
  }

  // }} operator-

  // operator*= {{

  constexpr modint &operator*=(const modint &__x) noexcept {
    value =
        static_cast<value_type>(value * static_cast<mul_type>(__x.value) % mod);
    return *this;
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type &
  operator*=(_Tp __x) noexcept {
    value = static_cast<value_type>(
        value * mul_type((__x %= mod) < 0 ? __x + mod : __x) % mod);
    return *this;
  }

  // }} operator*=

  // operator* {{

  constexpr modint operator*(const modint &__x) const noexcept {
    return {static_cast<mul_type>(value) * __x.value % mod, direct_ctor_tag};
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
  operator*(_Tp __x) const noexcept {
    __x %= mod;
    if (__x < 0) __x += mod;
    return {static_cast<mul_type>(value) * __x % mod, direct_ctor_tag};
  }

  template <class _Tp>
  constexpr friend
      typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
      operator*(_Tp __x, const modint &__y) noexcept {
    __x %= mod;
    if (__x < 0) __x += mod;
    return {static_cast<mul_type>(__x) * __y.value % mod, direct_ctor_tag};
  }

  // }} operator*

 protected:
  static value_type _mem(value_type __x) {
    static std::vector<value_type> __m{0, 1};
    static value_type __i = (__m.reserve(storage), 1);
    while (__i < __x) {
      ++__i;
      __m.emplace_back(mod - mul_type(mod / __i) * __m[mod % __i] % mod);
    }
    return __m[__x];
  }

  template <class _Tp>
  constexpr static
      typename std::enable_if<is_integral_ext<_Tp>::value, value_type>::type
      _div(mul_type __r, _Tp __x) noexcept {
    assert(__x != _Tp(0));
    if (!__r) return 0;

    std::make_signed_t<_Tp> __v{};
    bool __neg = __x < 0 ? __x = -__x, true : false;

    if (static_cast<decltype(storage)>(__x) < storage)
      __v = _mem(__x);
    else {
      decltype(__v) __y{mod}, __u{1}, __t;

      while (__x)
        __t = __y / __x, __y ^= __x ^= (__y -= __t * __x) ^= __x,
        __v ^= __u ^= (__v -= __t * __u) ^= __u;

      if (__y < 0) __neg ^= 1;
    }

    if (__neg)
      __v = 0 < __v ? mod - __v : -__v;
    else if (__v < 0)
      __v += mod;

    return __r == mul_type(1) ? static_cast<value_type>(__v)
                              : static_cast<value_type>(__r * __v % mod);
  }

 public:
  // operator/= {{

  constexpr modint &operator/=(const modint &__x) noexcept {
    if (value) value = _div(value, __x.value);
    return *this;
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type &
  operator/=(_Tp __x) noexcept {
    if (value) value = _div(value, __x %= mod);
    return *this;
  }

  // }} operator/=

  // operator/ {{

  constexpr modint operator/(const modint &__x) const noexcept {
    if (!value) return {};
    return {_div(value, __x.value), direct_ctor_tag};
  }

  template <class _Tp>
  constexpr typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
  operator/(_Tp __x) const noexcept {
    if (!value) return {};
    return {_div(value, __x %= mod), direct_ctor_tag};
  }

  template <class _Tp>
  constexpr friend
      typename std::enable_if<is_integral_ext<_Tp>::value, modint>::type
      operator/(_Tp __x, const modint &__y) noexcept {
    if (!__x) return {};
    if ((__x %= mod) < 0) __x += mod;
    return {_div(__x, __y.value), direct_ctor_tag};
  }

  // }} operator/

  constexpr modint inv() const noexcept { return _div(1, value); }

  template <class _Tp>
  constexpr std::__enable_if_t<is_integral_ext<_Tp>::value, modint> pow(
      _Tp __e) const noexcept {
    modint __r{1, direct_ctor_tag};

    for (modint __b{__e < 0 ? __e = -__e, _div(1, value) : value,
                              direct_ctor_tag};
         __e; __e >>= 1, __b *= __b)
      if (__e & 1) __r *= __b;

    return __r;
  }

  template <class _Tp>
  friend constexpr std::__enable_if_t<is_integral_ext<_Tp>::value, modint> pow(
      modint __b, _Tp __e) noexcept {
    if (__e < 0) {
      __e = -__e;
      __b.value = _div(1, __b.value);
    }

    modint __r{1, direct_ctor_tag};

    for (; __e; __e >>= 1, __b *= __b)
      if (__e & 1) __r *= __b;

    return __r;
  }

  constexpr modint sqrt() const noexcept {
    return {sqrt_mod(value, mod), direct_ctor_tag};
  }

  friend constexpr modint sqrt(const modint &__x) noexcept {
    return {sqrt_mod(__x.value, mod), direct_ctor_tag};
  }

  template <class _Os>
  friend _Os &operator<<(_Os &__os, const modint &__x) noexcept {
    return __os << __x.value;
  }

  friend std::istream &operator>>(std::istream &__is, modint &__x) noexcept {
    std::string __s;
    __is >> __s;
    bool __neg = false;
    if (__s.front() == '-') {
      __neg = true;
      __s.erase(__s.begin());
    }
    __x = 0;
    for (char __c : __s) __x = __x * 10 + (__c - '0');
    if (__neg) __x = -__x;
    return __is;
  }
};

template <auto _Mod, unsigned _Storage>
typename modint<_Mod, _Storage>::mod_type modint<_Mod, _Storage>::mod =
    _Mod > 0 ? _Mod : 0;

template <auto _Mod, unsigned _Storage>
unsigned modint<_Mod, _Storage>::storage = _Storage;

}  // namespace _modint_impl

template <auto _Mod, unsigned _Storage = 0,
          typename = std::enable_if_t<(_Mod > 0)>>
using modint = _modint_impl::modint<_Mod, _Storage>;

template <unsigned _Id = 0>
using modint_runtime = _modint_impl::modint<-(signed)_Id, 0>;

}  // namespace workspace
#line 7 "other/sister.cpp"

namespace workspace {

using mint = modint<1000003>;

int main() {
  // start here!

  int n, m;
  cin >> n >> m;
  if (!n) {
    return 1;
  }
  if (!m) {
    cout << (n % 2 ? 0 : (n != 2 ? 2 : 1)) << "\n";
    return 0;
  }

  vector<pair<int, int>> tree;

  // make tree representation
  {
    vector<pair<int, int>> tmp;
    while (m--) {
      int a, b;
      cin >> a >> b;
      --a, --b;
      if (a > b) {
        swap(a, b);
      }
      tmp.emplace_back(a, b);
    }

    auto [l, r] = *min_element(begin(tmp), end(tmp), [](auto x, auto y) {
      return x.second - x.first < y.second - y.first;
    });

    auto conv = [&](int i) -> int {
      if (i > l) {
        assert(i >= r);
        return i - r;
      }
      return n - r + i;
    };

    vector<vector<pair<int, int>>> at_lft(n), lenof(n);

    for (auto [x, y] : tmp) {
      x = conv(x);
      y = conv(y);
      if (x > y) {
        swap(x, y);
      }
      lenof[y - x].emplace_back(x, y);
    }

    for (auto &&ve : lenof) {
      for (auto &&[l, r] : ve) {
        at_lft[l].emplace_back(l, r);
      }
    }

    reverse(begin(at_lft), end(at_lft));

    for (auto &&ve : at_lft) {
      for (auto &&x : ve) {
        tree.push_back(x);
      }
    }

    n = r - l - 1;
    n %= 2;
  }

  struct dp {
    int left, right;
    mint ways[2][2];

    dp operator+(dp x) const {
      assert(right <= x.left);
      dp ret = {left, x.right};
      for (auto i1 : {0, 1}) {
        for (auto j2 : {0, 1}) {
          for (auto j1 : {0, 1}) {
            auto i2 = (x.left - right) % 2 ? j1 : !j1;
            ret.ways[i1][j2] += ways[i1][j1] * x.ways[i2][j2];
          }
        }
      }
      return ret;
    }
  };

  stack<dp> Q;

  for (auto [s, t] : tree) {
    dp here = {s, s, {1, 0, 0, 1}};
    while (!Q.empty()) {
      if (Q.top().right > t) {
        break;
      }
      here = here + Q.top();
      Q.pop();
    }
    here = here + dp{t, t, {1, 0, 0, 1}};
    here.ways[0][0] += here.ways[1][1];
    swap(here.ways[0][0], here.ways[1][1]);
    swap(here.ways[0][1], here.ways[1][0]);
    Q.push(here);
  }

  assert(Q.size() == 1);

  auto all = Q.top();
  cout << all.ways[0][n] + all.ways[1][!n] << "\n";

  return 0;
}

}  // namespace workspace

int main() {
  while (!workspace::main())
    ;
}
accuracy: 1
time_ms: 70
memory_kb: 9240
final_rank: 4

code_snippet: #include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#include<deque>
#include<iomanip>
#include<tuple>
#include<cassert>
#include<set>
using namespace std;
typedef long long int LL;
typedef pair<LL,LL> P;
typedef pair<LL,int> LP;
const int INF=1<<30;
const LL MAX=1000003;

void array_show(int *array,int array_n,char middle=' '){
    for(int i=0;i<array_n;i++)printf("%d%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(LL *array,int array_n,char middle=' '){
    for(int i=0;i<array_n;i++)printf("%lld%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(vector<int> &vec_s,int vec_n=-1,char middle=' '){
    if(vec_n==-1)vec_n=vec_s.size();
    for(int i=0;i<vec_n;i++)printf("%d%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}
void array_show(vector<LL> &vec_s,int vec_n=-1,char middle=' '){
    if(vec_n==-1)vec_n=vec_s.size();
    for(int i=0;i<vec_n;i++)printf("%lld%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}

vector<vector<P>> path;

int main(){
    int n,m;
    int i,j,k;
    LL a,b,c;
    map<int,int> m1;
    vector<P> vs,path2;

    while(cin>>n>>m){
        if(n==0)return 0;
        path.assign(n,vector<P>());
        vs.assign(m+10,P());
        path2.assign(m+10,P());
        m1.clear();
        for(i=0;i<m;i++){
            cin>>a>>b;
            a--,b--;
            if(a<b)swap(a,b);
            if((a-b)%2==0)continue;
            path[b].push_back(make_pair(a,i));
            path2[i]=make_pair(b,a);
        }
        path[0].push_back(make_pair(n-1,m));
        path2[m]=make_pair(0,n-1);
        for(i=0;i<n;i++){
            sort(path[i].begin(),path[i].end());
        }
        if(n%2){
            cout<<0<<endl;
            continue;
        }
        for(i=n-1;i>=0;i--){
            for(auto node:path[i]){
                j=node.second;
                a=path2[j].first,b=path2[j].second;
                vs[j].first=1,vs[j].second=1;
                while(1){
                    auto itr=m1.begin();
                    if(itr==m1.end() || itr->first>=b)break;
                    k=itr->second;
                    if((itr->first-a)%2==1){
                        vs[j].first*=vs[k].second;
                        vs[j].second*=vs[k].first;
                    }else{
                        vs[j].first*=vs[k].first;
                        vs[j].second*=vs[k].second;
                    }
                    vs[j].first%=MAX,vs[j].second%=MAX;
                    m1.erase(itr);
                }
                // cout<<a<<" "<<b<<endl;
                // cout<<vs[j].first<<" "<<vs[j].second<<endl;
                vs[j].second+=vs[j].first;
                vs[j].second%=MAX;
                m1[a]=j;
            }
        }
        cout<<vs[m].second<<endl;
    }
}
accuracy: 1
time_ms: 70
memory_kb: 6984
final_rank: 2

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
#define rep2(i,a,b) for(int i=a;i<=b;i++)
#define pb push_back
#define eb emplace_back

int in(){int x;cin>>x;return x;}


    
#define ll long long
vector<vector<int>> g;
vector<int> nxt;
constexpr ll MOD = 1000003;

main(){
    while(1){
        int n=in(),m=in();
        if(!n)return 0;
        g=vector<vector<int>>(n);
        vector<vector<int>> v(2);
        using P = pair<int,int> ;
        vector<P> ed;
        rep(i,m){
            int a=in()-1,b=in()-1;
            if(a>b)swap(a,b);
            if((a+b)&1){
                g[a].pb(b);
                v[a&1].pb(a);
                ed.eb(P(a,b));
            }
        }
        if(n&1){
            cout<<0<<endl;continue;
        }
        #define all(c) (c).begin(),(c).end()
        vector<pair<int,ll>> dp(n);
        ed.emplace_back(0,n-1);
        sort(all(ed),[](P x,P y){return x.second-x.first<y.second-y.first;});
        rep(i,n-1) dp[i] = P(i+1,1);
        for(auto p:ed){
            int a = p.first,b=p.second;
            ll ans = 1;
            int now = a+1;
            while(now!=b){
                ans=(ans*dp[now].second)%MOD;
                now = dp[now].first+1;
            }
            dp[a+1]={b-1,ans};
            now = a,ans = 1;
            while(now!=b+1){
                ans = (ans*dp[now].second)%MOD;
                now = dp[now].first+1;
            }
            ans+=dp[a+1].second;
            if(ans>=MOD)ans-=MOD;
            dp[a] = {b,ans};
        }
        cout<<dp[0].second<<endl;
    }
}
accuracy: 1
time_ms: 70
memory_kb: 6688
final_rank: 1

code_snippet: #include <bits/stdc++.h>

using namespace std;


using int64 = long long;
const int mod = 1000003;

const int64 infll = (1LL << 58) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;


template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 > &p) {
  os << p.first << " " << p.second;
  return os;
}

template< typename T1, typename T2 >
istream &operator>>(istream &is, pair< T1, T2 > &p) {
  is >> p.first >> p.second;
  return is;
}

template< typename T >
ostream &operator<<(ostream &os, const vector< T > &v) {
  for(int i = 0; i < (int) v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template< typename T >
istream &operator>>(istream &is, vector< T > &v) {
  for(T &in : v) is >> in;
  return is;
}

template< typename T1, typename T2 >
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template< typename T1, typename T2 >
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template< typename T = int64 >
vector< T > make_v(size_t a) {
  return vector< T >(a);
}

template< typename T, typename... Ts >
auto make_v(size_t a, Ts... ts) {
  return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...));
}

template< typename T, typename V >
typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {
  t = v;
}

template< typename T, typename V >
typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {
  for(auto &e : t) fill_v(e, v);
}

template< typename F >
struct FixPoint : F {
  FixPoint(F &&f) : F(forward< F >(f)) {}

  template< typename... Args >
  decltype(auto) operator()(Args &&... args) const {
    return F::operator()(*this, forward< Args >(args)...);
  }
};

template< typename F >
inline decltype(auto) MFP(F &&f) {
  return FixPoint< F >{forward< F >(f)};
}

template< typename T >
struct edge {
  int src, to;
  T cost;

  edge(int to, T cost) : src(-1), to(to), cost(cost) {}

  edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}

  edge &operator=(const int &x) {
    to = x;
    return *this;
  }

  operator int() const { return to; }
};

template< typename T >
using Edges = vector< edge< T > >;
template< typename T >
using WeightedGraph = vector< Edges< T > >;
using UnWeightedGraph = vector< vector< int > >;
template< typename T >
using Matrix = vector< vector< T > >;

/**
 * @bref Tree-Decomposition(木分解)
 */
struct DecompNode {
  vector< int > bag, child;

  DecompNode() = default;
};

struct TreeDecomposition {

  vector< vector< int > > g;

  explicit TreeDecomposition(int V) : g(V) {}

  void add_edge(int a, int b) {
    g[a].emplace_back(b);
    g[b].emplace_back(a);
  }

  vector< DecompNode > build() {
    const int N = (int) g.size();

    vector< int > used(N, -1), deg(N);
    queue< int > que;
    for(int i = 0; i < N; i++) {
      deg[i] = (int) g[i].size();
      if(deg[i] <= 2) que.emplace(i);
    }

    vector< set< int > > exists(N);
    for(int i = 0; i < N; i++) {
      for(auto &j : g[i]) {
        if(i < j) exists[i].emplace(j);
      }
    }

    vector< DecompNode > ret;
    ret.emplace_back();
    while(!que.empty()) {
      int idx = que.front();
      que.pop();
      if(deg[idx] > 2 || used[idx] != -1) continue;

      DecompNode r;
      r.bag.emplace_back(idx);
      int u = -1, v = -1;
      for(auto &to : g[idx]) {
        if(used[to] == -1) {
          (u == -1 ? u : v) = to;
          r.bag.emplace_back(to);
        } else if(used[to] >= 0) {
          r.child.emplace_back(used[to]);
          used[to] = -2;
        }
      }

      if(u == -1) {

      } else if(v == -1) {
        --deg[u];
      } else {
        if(u > v) swap(u, v);
        if(!exists[u].count(v)) {
          g[u].emplace_back(v);
          g[v].emplace_back(u);
          exists[u].emplace(v);
        } else {
          --deg[u];
          --deg[v];
        }
      }

      for(auto &to : g[idx]) {
        if(deg[to] <= 2) que.emplace(to);
      }

      used[idx] = (int) ret.size();
      deg[idx] = 0;
      ret.emplace_back(r);
    }
    for(int i = 0; i < N; i++) {
      if(deg[i] > 0) return {};
    }
    ret.front() = ret.back();
    ret.pop_back();
    return ret;
  }
};


void to_nice(vector< DecompNode > &g, int root = 0) {

  for(auto &p : g) {
    sort(p.bag.begin(), p.bag.end());
  }

  stack< int > st;
  st.emplace(root);

  while(!st.empty()) {
    int idx = st.top();
    st.pop();

    // join
    while(g[idx].child.size() > 2) {
      DecompNode r;
      r.child.resize(2);
      r.child[0] = g[idx].child.back();
      g[idx].child.pop_back();
      r.child[1] = g[idx].child.back();
      g[idx].child.pop_back();
      r.bag = g[idx].bag;
      g[idx].child.emplace_back((int) g.size());
      g.emplace_back(r);
    }

    if(g[idx].child.size() == 2) {
      for(auto &ch : g[idx].child) {
        if(g[ch].bag != g[idx].bag) {
          DecompNode r;
          r.child = {ch};
          r.bag = g[idx].bag;
          ch = (int) g.size();
          g.emplace_back(r);
        }
      }
    }

    // introduce / forget
    if(g[idx].child.size() == 1) {
      int &ch = g[idx].child[0];

      vector< int > latte, malta;
      set_difference(g[idx].bag.begin(), g[idx].bag.end(),
                     g[ch].bag.begin(), g[ch].bag.end(),
                     back_inserter(latte));
      set_difference(g[ch].bag.begin(), g[ch].bag.end(),
                     g[idx].bag.begin(), g[idx].bag.end(),
                     back_inserter(malta));
      if(latte.size() + malta.size() > 1) {
        DecompNode r;
        r.child = {ch};
        r.bag = g[idx].bag;
        if(!latte.empty()) {
          r.bag.erase(find(r.bag.begin(), r.bag.end(), latte.back()));
        } else {
          r.bag.emplace_back(malta.back());
        }
        ch = (int) g.size();
        g.emplace_back(r);
      }
    }

    // leaf
    if(g[idx].child.empty()) {
      if(g[idx].bag.size() > 1) {
        DecompNode r;
        r.bag = g[idx].bag;
        r.bag.pop_back();
        g[idx].child.emplace_back((int) g.size());
        g.emplace_back(r);
      }
    }

    for(auto &ch : g[idx].child) {
      st.emplace(ch);
    }
  }
}

template< int mod >
struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }

  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }

  static int get_mod() { return mod; }
};

using modint = ModInt< mod >;

int main() {
  int N, M;
  while(cin >> N >> M, N) {
    TreeDecomposition td(N);
    set< pair< int, int > > edges;
    for(int i = 0; i < N; i++) {
      td.add_edge(i, (i + 1) % N);
      edges.emplace(minmax(i, (i + 1) % N));
    }
    for(int i = 0; i < M; i++) {
      int a, b;
      cin >> a >> b;
      --a, --b;
      td.add_edge(a, b);
      edges.emplace(minmax(a, b));
    }

    if(N % 2) {
      cout << 0 << endl;
      continue;
    }

    auto t = td.build();
    to_nice(t);
    vector< vector< modint > > dps(t.size());
    vector< int > buff(N), buff2(N, -1);
    MFP([&](auto rec, int idx) -> void {

      auto &ch = t[idx].child;
      auto &bag = t[idx].bag;

      for(auto &to : ch) rec(to);
      vector< modint > dp(1 << bag.size());

      if(ch.empty()) { // leaf
        dp[0] = 1;
      } else if(ch.size() == 2) { // join
        for(int i = 0; i < dp.size(); i++) {
          for(int j = 0; j < dp.size(); j++) {
            if((i & j) == 0) dp[i | j] += dps[ch[0]][i] * dps[ch[1]][j];
          }
        }
      } else {
        auto &ch_bag = t[ch[0]].bag;
        auto &ch_dp = dps[ch[0]];

        for(int i = 0; i < bag.size(); i++) {
          buff[bag[i]] = 1 << i;
          buff2[bag[i]] = idx;
        }

        if(ch_bag.size() + 1 == bag.size()) { // introduce
          for(int i = 0; i < ch_dp.size(); i++) {
            int bit = 0;
            for(int j = 0; j < ch_bag.size(); j++) {
              if((i >> j) & 1) bit |= buff[ch_bag[j]];
            }
            dp[bit] = ch_dp[i];
          }
        } else { // forget
          int v = -1;
          for(int i = 0; i < ch_bag.size(); i++) {
            if(buff2[ch_bag[i]] != idx) v = ch_bag[i];
          }
          vector< int > ok_match(bag.size());
          for(int i = 0; i < bag.size(); i++) {
            ok_match[i] = edges.count(minmax(bag[i], v));
          }

          for(int i = 0; i < ch_dp.size(); i++) {
            int bit = 0;
            bool v_use = false;
            for(int j = 0; j < ch_bag.size(); j++) {
              if((i >> j) & 1) {
                if(v != ch_bag[j]) bit |= buff[ch_bag[j]];
              } else {
                if(v == ch_bag[j]) v_use = true;
              }
            }
            if(v_use) {
              for(int j = 0; j < bag.size(); j++) {
                if((bit >> j) & 1) continue;
                if(ok_match[j]) dp[bit | (1 << j)] += ch_dp[i];
              }
            } else {
              dp[bit] += ch_dp[i];
            }
          }
        }
      }
      dps[idx].swap(dp);
    })(0);
    auto &dp = dps[0];
    cout << dp.back() << endl;
  }
}
accuracy: 1
time_ms: 850
memory_kb: 56508
final_rank: 15

code_snippet: #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2405"

#include<bits/stdc++.h>
using namespace std;

#define call_from_test
#ifndef call_from_test
#include<bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
struct FastIO{
  FastIO(){
    cin.tie(0);
    ios::sync_with_stdio(0);
  }
}fastio_beet;
//END CUT HERE
#ifndef call_from_test
signed main(){
  return 0;
}
#endif

#ifndef call_from_test
#include<bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
// Assume Connected
struct NiceTree{
  vector< vector<int> > G;
  vector< set<int> > ex;
  vector<int> buff;
  NiceTree(int n):G(n),ex(n),buff(n){}

  void add_edge(int u,int v){
    if(u>v) swap(u,v);
    if(ex[u].count(v)) return;
    G[u].emplace_back(v);
    G[v].emplace_back(u);
    ex[u].emplace(v);
  }

  enum Type{LEAF, JOIN, INTRODUCE, FORGET};
  struct Node{
    int type;

    // index for G
    vector<int> bag;
    void add_vertex(int v){bag.emplace_back(v);}

    // index for T
    vector<int> child;
    void add_child(int v){child.emplace_back(v);}
  };

  vector<Node> T;
  void to_nice(){
    for(auto &v:T)
      sort(v.bag.begin(),v.bag.end());

    stack<int> st;
    st.emplace(0);

    while(!st.empty()){
      int v=st.top();st.pop();

      while(T[v].child.size()>2){
        Node r;
        r.add_child(T[v].child.back());
        T[v].child.pop_back();
        r.add_child(T[v].child.back());
        T[v].child.pop_back();
        r.bag=T[v].bag;
        T[v].add_child(T.size());
        T.emplace_back(r);
      }

      if(T[v].child.size()==2){
        for(auto &u:T[v].child){
          if(T[u].bag!=T[v].bag){
            Node r;
            r.add_child(u);
            r.bag=T[v].bag;
            u=T.size();
            T.emplace_back(r);
          }
        }
        T[v].type=JOIN;
      }

      if(T[v].child.size()==1){
        int &u=T[v].child[0];
        vector<int> latte,malta;
        auto &ps=T[v].bag;
        auto &qs=T[u].bag;
        set_difference(ps.begin(),ps.end(),qs.begin(),qs.end(),
                       back_inserter(latte));
        set_difference(qs.begin(),qs.end(),ps.begin(),ps.end(),
                       back_inserter(malta));
        if(latte.size()+malta.size()>1){
          Node r;
          r.add_child(u);
          r.bag=T[v].bag;
          if(!latte.empty()){
            r.bag.erase(find(r.bag.begin(),r.bag.end(),latte.back()));
          }else{
            r.bag.emplace_back(malta.back());
          }
          u=T.size();
          T.emplace_back(r);
        }
        if(T[v].bag.size()<T[u].bag.size()) T[v].type=FORGET;
        if(T[v].bag.size()>T[u].bag.size()) T[v].type=INTRODUCE;
      }

      if(T[v].child.empty()){
        if(T[v].bag.size()>1){
          Node r;
          r.bag=T[v].bag;
          r.bag.pop_back();
          T[v].type=INTRODUCE;
          T[v].add_child(T.size());
          T.emplace_back(r);
        }else{
          T[v].type=LEAF;
        }
      }

      for(auto &u:T[v].child)
        st.emplace(u);
    }
  }

  // root = 0
  void build(){
    int n=G.size();
    if(n<=3){
      Node r;
      for(int i=0;i<n;i++) r.add_vertex(i);
      T=vector<Node>({r});
      return to_nice();
    }

    vector<int> deg(n);
    queue<int> que;
    for(int i=0;i<n;i++){
      deg[i]=G[i].size();
      if(deg[i]<=2) que.emplace(i);
    }

    vector<int> used(n,-1);
    T.emplace_back();
    while(!que.empty()){
      int v=que.front();que.pop();
      if(deg[v]>2||used[v]!=-1) continue;
      Node r;
      r.add_vertex(v);

      int p=-1,q=-1;
      for(int u:G[v]){
        if(used[u]==-1){
          (p==-1?p:q)=u;
          r.add_vertex(u);
        }else if(used[u]>=0){
          r.add_child(used[u]);
          used[u]=-2;
        }
      }

      if(deg[v]==0){
        used[v]=T.size();
        T.emplace_back(r);
        continue;
      }

      if(q==-1){
        deg[p]--;
      }else{
        if(p>q) swap(p,q);
        if(!ex[p].count(q)){
          add_edge(p,q);
        }else{
          deg[p]--;
          deg[q]--;
        }
      }
      for(int u:G[v])
        if(deg[u]<=2) que.emplace(u);
      deg[v]=0;
      used[v]=T.size();
      T.emplace_back(r);
    }

    for(int i=0;i<n;i++){
      if(deg[i]>0){
        T={};
        return;
      }
    }

    T.front()=T.back();T.pop_back();
    to_nice();
  }

  template<typename F1,typename F2,typename F3,typename F4>
  void dfs(int v,F1 &leaf,F2 &join,F3 &introduce,F4 &forget){
    const auto &chd=T[v].child;
    for(int u:chd) dfs(u,leaf,join,introduce,forget);

    if(T[v].type==LEAF){
      leaf(v);
      return;
    }
    if(T[v].type==JOIN){
      join(v);
      return;
    }

    const auto &bag=T[v].bag;
    for(int i=0;i<(int)bag.size();i++)
      buff[bag[i]]=1<<i;

    const auto &chd_bag=T[chd[0]].bag;
    int dif=0;
    for(int b:bag) dif^=b;
    for(int b:chd_bag) dif^=b;

    if(T[v].type==INTRODUCE){
      introduce(v,dif);
      return;
    }
    if(T[v].type==FORGET){
      forget(v,dif);
      return;
    }
  }
};
//END CUT HERE
#ifndef call_from_test

#define call_from_test
#include "../tools/fastio.cpp"
#include "../tools/chminmax.cpp"
#undef call_from_test

signed CSA_SPECIAL_MVC(){
  int n,m;
  cin>>n>>m;
  NiceTree G(n);
  using P = pair<int, int>;
  set<P> es;
  for(int i=0;i<m;i++){
    int a,b;
    cin>>a>>b;
    a--;b--;
    G.add_edge(a,b);
    es.emplace(a,b);
    es.emplace(b,a);
  }

  G.build();
  auto &T=G.T;
  auto &buff=G.buff;

  vector< vector<int> > dps(T.size());

  const int INF = 1e9;
  auto base=
    [&](int v){
      const auto &bag=T[v].bag;
      auto &dp=dps[v];
      dp.assign(1<<bag.size(),-INF);
    };

  auto leaf=
    [&](int v){
      base(v);
      auto &dp=dps[v];
      dp[0]=0;
      dp[1]=1;
    };

  auto join=
    [&](int v){
      base(v);
      const auto &chd=T[v].child;
      auto &dp=dps[v];
      for(int i=0;i<(int)dp.size();i++)
        chmax(dp[i],dps[chd[0]][i]+dps[chd[1]][i]-__builtin_popcount(i));
    };

  auto introduce=
    [&](int v,int add){
      base(v);

      const auto &chd=T[v].child;
      const auto &chd_bag=T[chd[0]].bag;
      const auto &pr=dps[chd[0]];

      auto &dp=dps[v];
      for(int i=0;i<(int)pr.size();i++){
        int bit=0,valid=1;
        for(int j=0;j<(int)chd_bag.size();j++){
          if((~i>>j)&1) continue;
          bit|=buff[chd_bag[j]];
          valid&=!es.count(P(chd_bag[j],add));
        }
        assert(!(bit&buff[add]));
        if(valid) chmax(dp[bit|buff[add]],pr[i]+1);
        chmax(dp[bit],pr[i]);
      }
    };

  auto forget=
    [&](int v,int rmv){
      base(v);

      const auto &chd=T[v].child;
      const auto &chd_bag=T[chd[0]].bag;
      const auto &pr=dps[chd[0]];

      auto &dp=dps[v];
      for(int i=0;i<(int)pr.size();i++){
        int bit=0;
        for(int j=0;j<(int)chd_bag.size();j++){
          if((~i>>j)&1) continue;
          if(rmv!=chd_bag[j]) bit|=buff[chd_bag[j]];
        }
        chmax(dp[bit],pr[i]);
      }
    };

  G.dfs(0,leaf,join,introduce,forget);
  auto &dp=dps[0];
  cout<<n-*max_element(dp.begin(),dp.end())<<endl;
  return 0;
}
/*
  verified 2020/02/21
  https://csacademy.com/contest/archive/task/special-mvc/statement/
*/

signed main(){
  CSA_SPECIAL_MVC();
  return 0;
}
#endif

#ifndef call_from_test
#include<bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
template<typename T,T MOD = 1000000007>
struct Mint{
  static constexpr T mod = MOD;
  T v;
  Mint():v(0){}
  Mint(signed v):v(v){}
  Mint(long long t){v=t%MOD;if(v<0) v+=MOD;}

  Mint pow(long long k){
    Mint res(1),tmp(v);
    while(k){
      if(k&1) res*=tmp;
      tmp*=tmp;
      k>>=1;
    }
    return res;
  }

  static Mint add_identity(){return Mint(0);}
  static Mint mul_identity(){return Mint(1);}

  Mint inv(){return pow(MOD-2);}

  Mint& operator+=(Mint a){v+=a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator-=(Mint a){v+=MOD-a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator*=(Mint a){v=1LL*v*a.v%MOD;return *this;}
  Mint& operator/=(Mint a){return (*this)*=a.inv();}

  Mint operator+(Mint a) const{return Mint(v)+=a;}
  Mint operator-(Mint a) const{return Mint(v)-=a;}
  Mint operator*(Mint a) const{return Mint(v)*=a;}
  Mint operator/(Mint a) const{return Mint(v)/=a;}

  Mint operator-() const{return v?Mint(MOD-v):Mint(v);}

  bool operator==(const Mint a)const{return v==a.v;}
  bool operator!=(const Mint a)const{return v!=a.v;}
  bool operator <(const Mint a)const{return v <a.v;}

  static Mint comb(long long n,int k){
    Mint num(1),dom(1);
    for(int i=0;i<k;i++){
      num*=Mint(n-i);
      dom*=Mint(i+1);
    }
    return num/dom;
  }
};
template<typename T,T MOD> constexpr T Mint<T, MOD>::mod;
template<typename T,T MOD>
ostream& operator<<(ostream &os,Mint<T, MOD> m){os<<m.v;return os;}
//END CUT HERE
#ifndef call_from_test

//INSERT ABOVE HERE
signed ABC127_E(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  int h,w,k;
  cin>>h>>w>>k;
  using M = Mint<int>;

  M ans{0};
  for(int d=1;d<h;d++)
    ans+=M(d)*M(h-d)*M(w)*M(w);

  for(int d=1;d<w;d++)
    ans+=M(d)*M(w-d)*M(h)*M(h);

  ans*=M::comb(h*w-2,k-2);
  cout<<ans<<endl;
  return 0;
}
/*
  verified on 2019/06/12
  https://atcoder.jp/contests/abc127/tasks/abc127_e
*/

signed main(){
  //ABC127_E();
  return 0;
}
#endif

#undef call_from_test

signed main(){
  int n,m;
  while(cin>>n>>m,n){
    NiceTree G(n);
    using P = pair<int, int>;
    set<P> es;
    for(int i=0;i<n;i++){
      int j=(i+1)%n;
      G.add_edge(i,j);
      es.emplace(i,j);
      es.emplace(j,i);
    }
    for(int i=0;i<m;i++){
      int a,b;
      cin>>a>>b;
      a--;b--;
      G.add_edge(a,b);
      es.emplace(a,b);
      es.emplace(b,a);
    }
    if(n&1){
      cout<<0<<endl;
      continue;
    }
    G.build();
    auto &T=G.T;
    auto &buff=G.buff;

    using M = Mint<int, 1000003>;
    vector<vector<M>> dps(T.size());

    auto base=
      [&](int v){
        const auto &bag=T[v].bag;
        auto &dp=dps[v];
        dp.assign(1<<bag.size(),0);
      };

    auto leaf=
      [&](int v){
        base(v);
        auto &dp=dps[v];
        dp[0]=M(1);
      };

    auto join=
      [&](int v){
        base(v);
        const auto &chd=T[v].child;
        auto &dp=dps[v];

        for(int i=0;i<(int)dp.size();i++)
          for(int j=0;j<(int)dp.size();j++)
            if((i&j)==0) dp[i|j]+=dps[chd[0]][i]*dps[chd[1]][j];
      };

    auto introduce=
      [&](int v,int){
        base(v);
        const auto &chd=T[v].child;

        const auto &chd_bag=T[chd[0]].bag;
        const auto &pr=dps[chd[0]];

        auto &dp=dps[v];
        for(int i=0;i<(int)pr.size();i++){
          int bit=0;
          for(int j=0;j<(int)chd_bag.size();j++)
            if((i>>j)&1) bit|=buff[chd_bag[j]];
          dp[bit]=pr[i];
        }
      };

    auto forget=
      [&](int v,int rmv){
        base(v);
        const auto &bag=T[v].bag;
        const auto &chd=T[v].child;

        const auto &chd_bag=T[chd[0]].bag;
        const auto &pr=dps[chd[0]];

        auto &dp=dps[v];

        for(int i=0;i<(int)pr.size();i++){
          int bit=0,used=0;
          for(int j=0;j<(int)chd_bag.size();j++){
            if((~i>>j)&1) continue;
            if(rmv==chd_bag[j]) used=1;
            if(rmv!=chd_bag[j]) bit|=buff[chd_bag[j]];
          }
          if(!used){
            for(int j=0;j<(int)bag.size();j++){
              if((bit>>j)&1) continue;
              if(es.count(P(bag[j],rmv))) dp[bit|(1<<j)]+=pr[i];
            }
          }else{
            dp[bit]+=pr[i];
          }
        }
      };

    G.dfs(0,leaf,join,introduce,forget);

    auto &dp=dps[0];
    if(es.count(P(T[0].bag[0],T[0].bag[1])))
      dp.back()+=dp[0];
    cout<<dp.back()<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 1040
memory_kb: 64500
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}

// Assume Connected
struct NiceTree{
  vector< vector<int> > G;
  vector< set<int> > ex;
  NiceTree(int n):G(n),ex(n){}

  void add_edge(int u,int v){
    if(u>v) swap(u,v);
    if(ex[u].count(v)) return;
    G[u].emplace_back(v);
    G[v].emplace_back(u);
    ex[u].emplace(v);
  }

  enum Type{LEAF, INTRODUCE, FORGET, JOIN};
  struct Node{
    int type;

    // index for G
    vector<int> bag;
    void add_vertex(int v){bag.emplace_back(v);}

    // index for T
    vector<int> child;
    void add_child(int v){child.emplace_back(v);}
  };

  void to_nice(vector<Node> &T){
    for(auto &v:T)
      sort(v.bag.begin(),v.bag.end());

    stack<int> st;
    st.emplace(0);

    while(!st.empty()){
      int v=st.top();st.pop();

      while(T[v].child.size()>2){
        Node r;
        r.add_child(T[v].child.back());
        T[v].child.pop_back();
        r.add_child(T[v].child.back());
        T[v].child.pop_back();
        r.bag=T[v].bag;
        T[v].add_child(T.size());
        T.emplace_back(r);
      }

      if(T[v].child.size()==2){
        for(auto &u:T[v].child){
          if(T[u].bag!=T[v].bag){
            Node r;
            r.add_child(u);
            r.bag=T[v].bag;
            u=T.size();
            T.emplace_back(r);
          }
        }
        T[v].type=JOIN;
      }

      if(T[v].child.size()==1){
        int &u=T[v].child[0];
        vector<int> latte,malta;
        auto &ps=T[v].bag;
        auto &qs=T[u].bag;
        set_difference(ps.begin(),ps.end(),qs.begin(),qs.end(),
                       back_inserter(latte));
        set_difference(qs.begin(),qs.end(),ps.begin(),ps.end(),
                       back_inserter(malta));
        if(latte.size()+malta.size()>1){
          Node r;
          r.add_child(u);
          r.bag=T[v].bag;
          if(!latte.empty()){
            r.bag.erase(find(r.bag.begin(),r.bag.end(),latte.back()));
          }else{
            r.bag.emplace_back(malta.back());
          }
          u=T.size();
          T.emplace_back(r);
        }
        if(T[v].bag.size()<T[u].bag.size()) T[v].type=FORGET;
        if(T[v].bag.size()>T[u].bag.size()) T[v].type=INTRODUCE;
      }

      if(T[v].child.empty()){
        if(T[v].bag.size()>1){
          Node r;
          r.bag=T[v].bag;
          r.bag.pop_back();
          T[v].type=INTRODUCE;
          T[v].add_child(T.size());
          T.emplace_back(r);
        }else{
          T[v].type=LEAF;
        }
      }

      for(auto &u:T[v].child)
        st.emplace(u);
    }
  }

  // root = 0
  vector<Node> build(){
    int n=G.size();
    if(n<=3){
      Node r;
      for(int i=0;i<n;i++) r.add_vertex(i);
      return {r};
    }

    vector<int> deg(n);
    queue<int> que;
    for(int i=0;i<n;i++){
      deg[i]=G[i].size();
      if(deg[i]<=2) que.emplace(i);
    }

    vector<int> used(n,-1);
    vector<Node> T;
    T.emplace_back();
    while(!que.empty()){
      int v=que.front();que.pop();
      if(deg[v]==0||deg[v]>2||used[v]!=-1) continue;
      Node r;
      r.add_vertex(v);

      int p=-1,q=-1;
      for(int u:G[v]){
        if(used[u]==-1){
          (p==-1?p:q)=u;
          r.add_vertex(u);
        }else if(used[u]>=0){
          r.add_child(used[u]);
          used[u]=-2;
        }
      }
      if(q==-1){
        deg[p]--;
      }else{
        if(p>q) swap(p,q);
        if(!ex[p].count(q)){
          add_edge(p,q);
        }else{
          deg[p]--;
          deg[q]--;
        }
      }
      for(int u:G[v]){
        if(deg[u]==0) continue;
        if(deg[u]<=2) que.emplace(u);
      }
      used[v]=T.size();
      deg[v]=0;
      T.emplace_back(r);
    }

    for(int i=0;i<n;i++)
      if(deg[i]>0) return {};

    T.front()=T.back();T.pop_back();
    to_nice(T);
    return T;
  }
};


template<typename T,T MOD = 1000000007>
struct Mint{
  static constexpr T mod = MOD;
  T v;
  Mint():v(0){}
  Mint(signed v):v(v){}
  Mint(long long t){v=t%MOD;if(v<0) v+=MOD;}

  Mint pow(long long k){
    Mint res(1),tmp(v);
    while(k){
      if(k&1) res*=tmp;
      tmp*=tmp;
      k>>=1;
    }
    return res;
  }

  static Mint add_identity(){return Mint(0);}
  static Mint mul_identity(){return Mint(1);}

  Mint inv(){return pow(MOD-2);}

  Mint& operator+=(Mint a){v+=a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator-=(Mint a){v+=MOD-a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator*=(Mint a){v=1LL*v*a.v%MOD;return *this;}
  Mint& operator/=(Mint a){return (*this)*=a.inv();}

  Mint operator+(Mint a) const{return Mint(v)+=a;}
  Mint operator-(Mint a) const{return Mint(v)-=a;}
  Mint operator*(Mint a) const{return Mint(v)*=a;}
  Mint operator/(Mint a) const{return Mint(v)/=a;}

  Mint operator-() const{return v?Mint(MOD-v):Mint(v);}

  bool operator==(const Mint a)const{return v==a.v;}
  bool operator!=(const Mint a)const{return v!=a.v;}
  bool operator <(const Mint a)const{return v <a.v;}

  static Mint comb(long long n,int k){
    Mint num(1),dom(1);
    for(int i=0;i<k;i++){
      num*=Mint(n-i);
      dom*=Mint(i+1);
    }
    return num/dom;
  }
};
template<typename T,T MOD> constexpr T Mint<T, MOD>::mod;
template<typename T,T MOD>
ostream& operator<<(ostream &os,Mint<T, MOD> m){os<<m.v;return os;}


template<typename F>
struct FixPoint : F{
  FixPoint(F&& f):F(forward<F>(f)){}
  template<typename... Args>
  decltype(auto) operator()(Args&&... args) const{
    return F::operator()(*this,forward<Args>(args)...);
  }
};
template<typename F>
inline decltype(auto) MFP(F&& f){
  return FixPoint<F>{forward<F>(f)};
}


struct FastIO{
  FastIO(){
    cin.tie(0);
    ios::sync_with_stdio(0);
  }
}fastio_beet;

//INSERT ABOVE HERE
signed main(){
  int n,m;
  while(cin>>n>>m,n){
    NiceTree G(n);
    using P = pair<int, int>;
    set<P> es;
    for(int i=0;i<n;i++){
      int j=(i+1)%n;
      G.add_edge(i,j);
      es.emplace(i,j);
      es.emplace(j,i);
    }
    for(int i=0;i<m;i++){
      int a,b;
      cin>>a>>b;
      a--;b--;
      G.add_edge(a,b);
      es.emplace(a,b);
      es.emplace(b,a);
    }
    if(n&1){
      cout<<0<<endl;
      continue;
    }
    auto T=G.build();

    using M = Mint<int, 1000003>;
    vector<vector<M>> dps(T.size());
    vector<int> buff1(n),buff2(n,-1);
    MFP([&](auto dfs,int v)->void{
          const auto &bag=T[v].bag;
          const auto &chd=T[v].child;

          for(int u:chd) dfs(u);
          auto &dp=dps[v];
          dp.assign(1<<bag.size(),0);

          if(T[v].type==NiceTree::LEAF){
            dp[0]=M(1);
            return;
          }

          if(T[v].type==NiceTree::JOIN){
            for(int i=0;i<(int)dp.size();i++)
              for(int j=0;j<(int)dp.size();j++)
                if((i&j)==0) dp[i|j]+=dps[chd[0]][i]*dps[chd[1]][j];
            return;
          }

          const auto &chd_bag=T[chd[0]].bag;
          const auto &pr=dps[chd[0]];

          for(int i=0;i<(int)bag.size();i++){
            buff1[bag[i]]=1<<i;
            buff2[bag[i]]=v;
          }

          if(T[v].type==NiceTree::INTRODUCE){
            for(int i=0;i<(int)pr.size();i++){
              int bit=0;
              for(int j=0;j<(int)chd_bag.size();j++)
                if((i>>j)&1) bit|=buff1[chd_bag[j]];
              dp[bit]=pr[i];
            }
            return;
          }

          if(T[v].type==NiceTree::FORGET){
            int add=-1;
            for(int i=0;i<(int)chd_bag.size();i++)
              if(buff2[chd_bag[i]]!=v) add=chd_bag[i];

            vector<int> ex(bag.size());
            for(int i=0;i<(int)bag.size();i++)
              ex[i]=es.count(P(bag[i],add));

            for(int i=0;i<(int)pr.size();i++){
              int bit=0,used=0;
              for(int j=0;j<(int)chd_bag.size();j++){
                if((~i>>j)&1) continue;
                if(add==chd_bag[j]) used=1;
                if(add!=chd_bag[j]) bit|=buff1[chd_bag[j]];
              }
              if(!used){
                for(int j=0;j<(int)bag.size();j++){
                  if((bit>>j)&1) continue;
                  if(ex[j]) dp[bit|(1<<j)]+=pr[i];
                }
              }else{
                dp[bit]+=pr[i];
              }
            }
            return;
          }
        })(0);

    auto &dp=dps[0];
    if(es.count(P(T[0].bag[0],T[0].bag[1])))
      dp.back()+=dp[0];
    cout<<dp.back()<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 1040
memory_kb: 67912
final_rank: 18

code_snippet: #include <bits/stdc++.h>

using namespace std;


using int64 = long long;
const int mod = 1000003;

const int64 infll = (1LL << 58) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;


template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 > &p) {
  os << p.first << " " << p.second;
  return os;
}

template< typename T1, typename T2 >
istream &operator>>(istream &is, pair< T1, T2 > &p) {
  is >> p.first >> p.second;
  return is;
}

template< typename T >
ostream &operator<<(ostream &os, const vector< T > &v) {
  for(int i = 0; i < (int) v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template< typename T >
istream &operator>>(istream &is, vector< T > &v) {
  for(T &in : v) is >> in;
  return is;
}

template< typename T1, typename T2 >
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template< typename T1, typename T2 >
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template< typename T = int64 >
vector< T > make_v(size_t a) {
  return vector< T >(a);
}

template< typename T, typename... Ts >
auto make_v(size_t a, Ts... ts) {
  return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...));
}

template< typename T, typename V >
typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {
  t = v;
}

template< typename T, typename V >
typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {
  for(auto &e : t) fill_v(e, v);
}

template< typename F >
struct FixPoint : F {
  FixPoint(F &&f) : F(forward< F >(f)) {}

  template< typename... Args >
  decltype(auto) operator()(Args &&... args) const {
    return F::operator()(*this, forward< Args >(args)...);
  }
};

template< typename F >
inline decltype(auto) MFP(F &&f) {
  return FixPoint< F >{forward< F >(f)};
}

struct DecompNode {
  vector< int > bag, child;

  DecompNode() = default;
};

struct TreeDecomposition {

  vector< vector< int > > g;

  explicit TreeDecomposition(int V) : g(V) {}

  void add_edge(int a, int b) {
    g[a].emplace_back(b);
    g[b].emplace_back(a);
  }

  vector< DecompNode > build() {
    const int N = (int) g.size();

    if(N <= 3) {
      DecompNode r;
      for(int i = 0; i < N; i++) r.bag.emplace_back(i);
      return {r};
    }

    vector< int > used(N, -1), deg(N);
    queue< int > que;
    for(int i = 0; i < N; i++) {
      deg[i] = (int) g[i].size();
      if(deg[i] <= 2) que.emplace(i);
    }

    vector< set< int > > exists(N);
    for(int i = 0; i < N; i++) {
      for(auto &j : g[i]) {
        if(i < j) exists[i].emplace(j);
      }
    }

    vector< DecompNode > ret;
    while(!que.empty()) {
      int idx = que.front();
      que.pop();
      if(deg[idx] == 0 || deg[idx] > 2 || used[idx] != -1) continue;
      DecompNode r;
      r.bag.emplace_back(idx);
      int u = -1, v = -1;
      for(auto &to : g[idx]) {
        if(used[to] == -1) {
          (u == -1 ? u : v) = to;
          r.bag.emplace_back(to);
        } else if(used[to] >= 0) {
          r.child.emplace_back(used[to]);
          used[to] = -2;
        }
      }

      if(v == -1) {
        --deg[u];
      } else {
        if(u > v) swap(u, v);
        if(!exists[u].count(v)) {
          g[u].emplace_back(v);
          g[v].emplace_back(u);
          exists[u].emplace(v);
        } else {
          --deg[u];
          --deg[v];
        }
      }

      for(auto &to : g[idx]) {
        if(deg[to] == 0) continue;
        if(deg[to] <= 2) que.emplace(to);
      }

      used[idx] = (int) ret.size();
      deg[idx] = 0;
      ret.emplace_back(r);
    }
    for(int i = 0; i < N; i++) {
      if(deg[i] > 0) return {};
    }
    return ret;
  }
};

int to_nice(vector< DecompNode > &g, int root = -1) {
  if(root == -1) root = (int) g.size() - 1;

  for(auto &p : g) {
    sort(p.bag.begin(), p.bag.end());
  }

  stack< int > st;
  st.emplace(root);

  while(!st.empty()) {
    int idx = st.top();
    st.pop();

    // join
    while(g[idx].child.size() > 2) {
      DecompNode r;
      r.child.resize(2);
      r.child[0] = g[idx].child.back();
      g[idx].child.pop_back();
      r.child[1] = g[idx].child.back();
      g[idx].child.pop_back();
      r.bag = g[idx].bag;
      g[idx].child.emplace_back((int) g.size());
      g.emplace_back(r);
    }

    if(g[idx].child.size() == 2) {
      for(auto &ch : g[idx].child) {
        if(g[ch].bag != g[idx].bag) {
          DecompNode r;
          r.child.resize(1);
          r.child[0] = ch;
          r.bag = g[idx].bag;
          ch = (int) g.size();
          g.emplace_back(r);
        }
      }
    }

    // introduce / forgot
    if(g[idx].child.size() == 1) {
      int &ch = g[idx].child[0];

      vector< int > latte, malta;
      set_difference(g[idx].bag.begin(), g[idx].bag.end(),
                     g[ch].bag.begin(), g[ch].bag.end(),
                     back_inserter(latte));
      set_difference(g[ch].bag.begin(), g[ch].bag.end(),
                     g[idx].bag.begin(), g[idx].bag.end(),
                     back_inserter(malta));
      if(latte.size() + malta.size() > 1) {
        DecompNode r;
        r.child = {ch};
        r.bag = g[idx].bag;
        if(!latte.empty()) {
          r.bag.erase(find(r.bag.begin(), r.bag.end(), latte.back()));
        } else {
          r.bag.emplace_back(malta.back());
        }
        ch = (int) g.size();
        g.emplace_back(r);
      }
    }

    // leaf
    if(g[idx].child.empty()) {
      if(g[idx].bag.size() > 1) {
        DecompNode r;
        r.bag = g[idx].bag;
        r.bag.pop_back();
        g[idx].child.emplace_back((int) g.size());
        g.emplace_back(r);
      }
    }

    for(auto &ch : g[idx].child) {
      st.emplace(ch);
    }
  }
  return root;
}

template< int mod >
struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt &operator^=(int64_t n) {
    int y = x;
    x = 1;
    while(n > 0) {
      if(n & 1) x = 1LL * x * y % mod;
      y = 1LL * y * y % mod;
      n >>= 1;
    }
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

  ModInt operator^(const int64_t n) const { return ModInt(*this) ^= n; }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      a -= t * b;
      swap(a, b);
      u -= t * v;
      swap(u, v);
    }
    return ModInt(u);
  }

  friend ostream &operator<<(ostream &os, const ModInt< mod > &p) {
    return os << p.x;
  }

  friend istream &operator>>(istream &is, ModInt< mod > &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }
};

using modint = ModInt< mod >;

int main() {
  int N, M;
  while(cin >> N >> M, N) {
    TreeDecomposition g(N);
    set< pair< int, int > > edges;
    for(int i = 0; i < M; i++) {
      int a, b;
      cin >> a >> b;
      --a, --b;
      edges.emplace(minmax(a, b));
      g.add_edge(a, b);
    }
    if(N % 2) {
      cout << 0 << endl;
      continue;
    }
    for(int i = 0; i < N; i++) {
      edges.emplace(minmax(i, (i + 1) % N));
      g.add_edge(i, (i + 1) % N);
    }
    auto t = g.build();
    int root = to_nice(t);
    vector< vector< modint > > dps(t.size());
    vector< int > buff(N), buff2(N, -1);

    MFP([&](auto rec, int idx) -> void {

      auto &ch = t[idx].child;
      auto &bag = t[idx].bag;

      for(auto &to : ch) rec(to);
      vector< modint > dp(1 << bag.size());

      if(ch.empty()) { // leaf
        dp[0] = 1;
      } else if(ch.size() == 2) { // join
        for(int i = 0; i < dp.size(); i++) {
          for(int j = 0; j < dp.size(); j++) {
            if((i & j) == 0) dp[i | j] += dps[ch[0]][i] * dps[ch[1]][j];
          }
        }
      } else {
        auto &ch_bag = t[ch[0]].bag;
        auto &ch_dp = dps[ch[0]];

        for(int i = 0; i < bag.size(); i++) {
          buff[bag[i]] = 1 << i;
          buff2[bag[i]] = idx;
        }

        if(ch_bag.size() + 1 == bag.size()) { // introduce
          for(int i = 0; i < ch_dp.size(); i++) {
            int bit = 0;
            for(int j = 0; j < ch_bag.size(); j++) {
              if((i >> j) & 1) bit |= buff[ch_bag[j]];
            }
            dp[bit] = ch_dp[i];
          }
        } else { // forgot
          int v = -1;
          for(int i = 0; i < ch_bag.size(); i++) {
            if(buff2[ch_bag[i]] != idx) v = ch_bag[i];
          }
          vector< int > ok_match(bag.size());
          for(int i = 0; i < bag.size(); i++) {
            ok_match[i] = edges.count(minmax(bag[i], v));
          }
          for(int i = 0; i < ch_dp.size(); i++) {
            int bit = 0;
            bool v_use = false;
            for(int j = 0; j < ch_bag.size(); j++) {
              if((i >> j) & 1) {
                if(v != ch_bag[j]) bit |= buff[ch_bag[j]];
              } else {
                if(v == ch_bag[j]) v_use = true;
              }
            }
            if(v_use) {
              for(int j = 0; j < bag.size(); j++) {
                if((bit >> j) & 1) continue;
                if(ok_match[j]) dp[bit | (1 << j)] += ch_dp[i];
              }
            } else {
              dp[bit] += ch_dp[i];
            }
          }
        }
      }
      dps[idx].swap(dp);
    })(root);
    auto &dp = dps[root];
    if(edges.count(minmax(t[root].bag[0], t[root].bag[1]))) dp.back() += dp[0];
    cout << dp.back() << endl;
  }
}
accuracy: 1
time_ms: 780
memory_kb: 57796
final_rank: 16

code_snippet: #include <bits/stdc++.h>

using namespace std;


using int64 = long long;
const int mod = 1000003;

const int64 infll = (1LL << 58) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;


template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 > &p) {
  os << p.first << " " << p.second;
  return os;
}

template< typename T1, typename T2 >
istream &operator>>(istream &is, pair< T1, T2 > &p) {
  is >> p.first >> p.second;
  return is;
}

template< typename T >
ostream &operator<<(ostream &os, const vector< T > &v) {
  for(int i = 0; i < (int) v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template< typename T >
istream &operator>>(istream &is, vector< T > &v) {
  for(T &in : v) is >> in;
  return is;
}

template< typename T1, typename T2 >
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template< typename T1, typename T2 >
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template< typename T = int64 >
vector< T > make_v(size_t a) {
  return vector< T >(a);
}

template< typename T, typename... Ts >
auto make_v(size_t a, Ts... ts) {
  return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...));
}

template< typename T, typename V >
typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {
  t = v;
}

template< typename T, typename V >
typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {
  for(auto &e : t) fill_v(e, v);
}

template< typename F >
struct FixPoint : F {
  FixPoint(F &&f) : F(forward< F >(f)) {}

  template< typename... Args >
  decltype(auto) operator()(Args &&... args) const {
    return F::operator()(*this, forward< Args >(args)...);
  }
};

template< typename F >
inline decltype(auto) MFP(F &&f) {
  return FixPoint< F >{forward< F >(f)};
}

struct DecompNode {
  vector< int > bag, child;

  DecompNode() = default;
};

struct TreeDecomposition {

  vector< vector< int > > g;

  explicit TreeDecomposition(int V) : g(V) {}

  void add_edge(int a, int b) {
    g[a].emplace_back(b);
    g[b].emplace_back(a);
  }

  vector< DecompNode > build() {
    const int N = (int) g.size();

    if(N <= 3) {
      DecompNode r;
      for(int i = 0; i < N; i++) r.bag.emplace_back(i);
      return {r};
    }

    vector< int > used(N, -1), deg(N);
    queue< int > que;
    for(int i = 0; i < N; i++) {
      deg[i] = (int) g[i].size();
      if(deg[i] <= 2) que.emplace(i);
    }

    vector< set< int > > exists(N);
    for(int i = 0; i < N; i++) {
      for(auto &j : g[i]) {
        if(i < j) exists[i].emplace(j);
      }
    }

    vector< DecompNode > ret;
    while(!que.empty()) {
      int idx = que.front();
      que.pop();
      if(deg[idx] == 0 || deg[idx] > 2 || used[idx] != -1) continue;
      DecompNode r;
      r.bag.emplace_back(idx);
      int u = -1, v = -1;
      for(auto &to : g[idx]) {
        if(used[to] == -1) {
          (u == -1 ? u : v) = to;
          r.bag.emplace_back(to);
        } else if(used[to] >= 0) {
          r.child.emplace_back(used[to]);
          used[to] = -2;
        }
      }

      if(v == -1) {
        --deg[u];
      } else {
        if(u > v) swap(u, v);
        if(!exists[u].count(v)) {
          g[u].emplace_back(v);
          g[v].emplace_back(u);
          exists[u].emplace(v);
        } else {
          --deg[u];
          --deg[v];
        }
      }

      for(auto &to : g[idx]) {
        if(deg[to] == 0) continue;
        if(deg[to] <= 2) que.emplace(to);
      }

      used[idx] = (int) ret.size();
      deg[idx] = 0;
      ret.emplace_back(r);
    }
    for(int i = 0; i < N; i++) {
      if(deg[i] > 0) return {};
    }
    return ret;
  }
};

int to_nice(vector< DecompNode > &g, int root = -1) {
  if(root == -1) root = (int) g.size() - 1;

  for(auto &p : g) {
    sort(p.bag.begin(), p.bag.end());
  }

  stack< int > st;
  st.emplace(root);

  while(!st.empty()) {
    int idx = st.top();
    st.pop();

    // join
    while(g[idx].child.size() > 2) {
      DecompNode r;
      r.child.resize(2);
      r.child[0] = g[idx].child.back();
      g[idx].child.pop_back();
      r.child[1] = g[idx].child.back();
      g[idx].child.pop_back();
      r.bag = g[idx].bag;
      g[idx].child.emplace_back((int) g.size());
      g.emplace_back(r);
    }

    if(g[idx].child.size() == 2) {
      for(auto &ch : g[idx].child) {
        if(g[ch].bag != g[idx].bag) {
          DecompNode r;
          r.child.resize(1);
          r.child[0] = ch;
          r.bag = g[idx].bag;
          ch = (int) g.size();
          g.emplace_back(r);
        }
      }
    }

    // introduce / forgot
    if(g[idx].child.size() == 1) {
      int &ch = g[idx].child[0];

      vector< int > latte, malta;
      set_difference(g[idx].bag.begin(), g[idx].bag.end(),
                     g[ch].bag.begin(), g[ch].bag.end(),
                     back_inserter(latte));
      set_difference(g[ch].bag.begin(), g[ch].bag.end(),
                     g[idx].bag.begin(), g[idx].bag.end(),
                     back_inserter(malta));
      if(latte.size() + malta.size() > 1) {
        DecompNode r;
        r.child = {ch};
        r.bag = g[idx].bag;
        if(!latte.empty()) {
          r.bag.erase(find(r.bag.begin(), r.bag.end(), latte.back()));
        } else {
          r.bag.emplace_back(malta.back());
        }
        ch = (int) g.size();
        g.emplace_back(r);
      }
    }

    for(auto &ch : g[idx].child) {
      st.emplace(ch);
    }
  }
  return root;
}

template< int mod >
struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt &operator^=(int64_t n) {
    int y = x;
    x = 1;
    while(n > 0) {
      if(n & 1) x = 1LL * x * y % mod;
      y = 1LL * y * y % mod;
      n >>= 1;
    }
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

  ModInt operator^(const int64_t n) const { return ModInt(*this) ^= n; }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      a -= t * b;
      swap(a, b);
      u -= t * v;
      swap(u, v);
    }
    return ModInt(u);
  }

  friend ostream &operator<<(ostream &os, const ModInt< mod > &p) {
    return os << p.x;
  }

  friend istream &operator>>(istream &is, ModInt< mod > &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }
};

using modint = ModInt< mod >;

int main() {
  int N, M;
  while(cin >> N >> M, N) {
    TreeDecomposition g(N);
    set< pair< int, int > > edges;
    for(int i = 0; i < M; i++) {
      int a, b;
      cin >> a >> b;
      --a, --b;
      edges.emplace(minmax(a, b));
      g.add_edge(a, b);
    }
    if(N % 2) {
      cout << 0 << endl;
      continue;
    }
    for(int i = 0; i < N; i++) {
      edges.emplace(minmax(i, (i + 1) % N));
      g.add_edge(i, (i + 1) % N);
    }
    auto t = g.build();
    int root = to_nice(t);
    vector< vector< modint > > dps(t.size());
    vector< int > buff(N), buff2(N, -1);

    MFP([&](auto rec, int idx) -> void {

      auto &ch = t[idx].child;
      auto &bag = t[idx].bag;

      for(auto &to : ch) rec(to);
      vector< modint > dp(1 << bag.size());

      if(ch.empty()) { // leaf
        dp[0] = 1;
      } else if(ch.size() == 2) { // join
        for(int i = 0; i < dp.size(); i++) {
          for(int j = 0; j < dp.size(); j++) {
            if((i & j) == 0) dp[i | j] += dps[ch[0]][i] * dps[ch[1]][j];
          }
        }
      } else {
        auto &ch_bag = t[ch[0]].bag;
        auto &ch_dp = dps[ch[0]];

        for(int i = 0; i < bag.size(); i++) {
          buff[bag[i]] = 1 << i;
          buff2[bag[i]] = idx;
        }

        if(ch_bag.size() + 1 == bag.size()) { // introduce
          for(int i = 0; i < ch_dp.size(); i++) {
            int bit = 0;
            for(int j = 0; j < ch_bag.size(); j++) {
              if((i >> j) & 1) bit |= buff[ch_bag[j]];
            }
            dp[bit] = ch_dp[i];
          }
        } else { // forgot
          int v = -1;
          for(int i = 0; i < ch_bag.size(); i++) {
            if(buff2[ch_bag[i]] != idx) v = ch_bag[i];
          }
          vector< int > ok_match(bag.size());
          for(int i = 0; i < bag.size(); i++) {
            ok_match[i] = edges.count(minmax(bag[i], v));
          }
          for(int i = 0; i < ch_dp.size(); i++) {
            int bit = 0;
            bool v_use = false;
            for(int j = 0; j < ch_bag.size(); j++) {
              if((i >> j) & 1) {
                if(v != ch_bag[j]) bit |= buff[ch_bag[j]];
              } else {
                if(v == ch_bag[j]) v_use = true;
              }
            }
            if(v_use) {
              for(int j = 0; j < bag.size(); j++) {
                if((bit >> j) & 1) continue;
                if(ok_match[j]) dp[bit | (1 << j)] += ch_dp[i];
              }
            } else {
              dp[bit] += ch_dp[i];
            }
          }
        }
      }
      dps[idx].swap(dp);
    })(root);
    auto &dp = dps[root];
    if(edges.count(minmax(t[root].bag[0], t[root].bag[1]))) dp.back() += dp[0];
    cout << dp.back() << endl;
  }
}
accuracy: 1
time_ms: 740
memory_kb: 52380
final_rank: 12

code_snippet: #include <bits/stdc++.h>

using namespace std;


using int64 = long long;
const int mod = 1000003;

const int64 infll = (1LL << 62) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;


template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 > &p) {
  os << p.first << " " << p.second;
  return os;
}

template< typename T1, typename T2 >
istream &operator>>(istream &is, pair< T1, T2 > &p) {
  is >> p.first >> p.second;
  return is;
}

template< typename T >
ostream &operator<<(ostream &os, const vector< T > &v) {
  for(int i = 0; i < (int) v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template< typename T >
istream &operator>>(istream &is, vector< T > &v) {
  for(T &in : v) is >> in;
  return is;
}

template< typename T1, typename T2 >
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template< typename T1, typename T2 >
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template< typename T = int64 >
vector< T > make_v(size_t a) {
  return vector< T >(a);
}

template< typename T, typename... Ts >
auto make_v(size_t a, Ts... ts) {
  return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...));
}

template< typename T, typename V >
typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {
  t = v;
}

template< typename T, typename V >
typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {
  for(auto &e : t) fill_v(e, v);
}

template< typename F >
struct FixPoint : F {
  FixPoint(F &&f) : F(forward< F >(f)) {}

  template< typename... Args >
  decltype(auto) operator()(Args &&... args) const {
    return F::operator()(*this, forward< Args >(args)...);
  }
};

template< typename F >
inline decltype(auto) MFP(F &&f) {
  return FixPoint< F >{forward< F >(f)};
}

struct DecompNode {
  vector< int > bag, child;

  DecompNode() = default;
};

struct TreeDecomposition {

  vector< vector< int > > g;

  explicit TreeDecomposition(int V) : g(V) {}

  void add_edge(int a, int b) {
    g[a].emplace_back(b);
    g[b].emplace_back(a);
  }

  vector< DecompNode > build() {
    const int N = (int) g.size();

    if(N <= 3) {
      DecompNode r;
      for(int i = 0; i < N; i++) r.bag.emplace_back(i);
      return {r};
    }

    vector< int > used(N, -1), deg(N);
    queue< int > que;
    for(int i = 0; i < N; i++) {
      deg[i] = (int) g[i].size();
      if(deg[i] == 2) que.emplace(i);
    }

    vector< set< int > > exists(N);
    for(int i = 0; i < N; i++) {
      for(auto &j : g[i]) {
        if(i < j) exists[i].emplace(j);
      }
    }

    vector< DecompNode > ret;
    while(!que.empty()) {
      int idx = que.front();
      que.pop();
      if(deg[idx] != 2 || used[idx] != -1) continue;

      DecompNode r;
      r.bag.emplace_back(idx);
      int u = -1, v = -1;
      for(auto &to : g[idx]) {
        if(used[to] == -1) {
          (u == -1 ? u : v) = to;
          r.bag.emplace_back(to);
        } else if(used[to] >= 0) {
          r.child.emplace_back(used[to]);
          used[to] = -2;
        }
      }

      if(u > v) swap(u, v);
      if(!exists[u].count(v)) {
        g[u].emplace_back(v);
        g[v].emplace_back(u);
        exists[u].emplace(v);
      } else {
        --deg[u];
        --deg[v];
      }

      for(auto &to : g[idx]) {
        if(deg[to] == 2) que.emplace(to);
      }

      used[idx] = (int) ret.size();
      deg[idx] = 0;
      ret.emplace_back(r);
    }

    DecompNode r;
    for(int i = 0; i < N; i++) {
      if(deg[i] == 1) r.bag.emplace_back(i);
    }
    if(r.bag.size() != 2) return {};
    for(auto &to : g[r.bag[0]]) {
      if(used[to] >= 0) {
        r.child.emplace_back(used[to]);
      }
    }
    ret.emplace_back(r);
    return ret;
  }
};


int to_nice(vector< DecompNode > &g, int root = -1) {
  if(root == -1) root = (int) g.size() - 1;

  for(auto &p : g) {
    sort(p.bag.begin(), p.bag.end());
  }

  stack< int > st;
  st.emplace(root);

  while(!st.empty()) {
    int idx = st.top();
    st.pop();

    // join
    while(g[idx].child.size() > 2) {
      DecompNode r;
      r.child.resize(2);
      r.child[0] = g[idx].child.back();
      g[idx].child.pop_back();
      r.child[1] = g[idx].child.back();
      g[idx].child.pop_back();
      r.bag = g[idx].bag;
      g[idx].child.emplace_back((int) g.size());
      g.emplace_back(r);
    }

    if(g[idx].child.size() == 2) {
      for(auto &ch : g[idx].child) {
        if(g[ch].bag != g[idx].bag) {
          DecompNode r;
          r.child.resize(1);
          r.child[0] = ch;
          r.bag = g[idx].bag;
          ch = (int) g.size();
          g.emplace_back(r);
        }
      }
    }

    // introduce / forgot
    if(g[idx].child.size() == 1) {
      int &ch = g[idx].child[0];

      vector< int > latte, malta;
      set_difference(g[idx].bag.begin(), g[idx].bag.end(),
                     g[ch].bag.begin(), g[ch].bag.end(),
                     back_inserter(latte));
      set_difference(g[ch].bag.begin(), g[ch].bag.end(),
                     g[idx].bag.begin(), g[idx].bag.end(),
                     back_inserter(malta));
      if(latte.size() + malta.size() > 1) {
        DecompNode r;
        r.child = {ch};
        r.bag = g[idx].bag;
        if(!latte.empty()) {
          r.bag.erase(find(r.bag.begin(), r.bag.end(), latte.back()));
        } else {
          r.bag.emplace_back(malta.back());
        }
        ch = (int) g.size();
        g.emplace_back(r);
      }
    }

    for(auto &ch : g[idx].child) {
      st.emplace(ch);
    }
  }
  return root;
}

template< int mod >
struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }

  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }

  static int get_mod() { return mod; }
};

using modint = ModInt< mod >;

int main() {
  int N, M;
  while(cin >> N >> M, N) {
    TreeDecomposition g(N);
    set< pair< int, int > > edges;
    for(int i = 0; i < M; i++) {
      int a, b;
      cin >> a >> b;
      --a, --b;
      edges.emplace(minmax(a, b));
      g.add_edge(a, b);
    }
    if(N % 2) {
      cout << 0 << endl;
      continue;
    }
    for(int i = 0; i < N; i++) {
      edges.emplace(minmax(i, (i + 1) % N));
      g.add_edge(i, (i + 1) % N);
    }
    auto t = g.build();
    int root = to_nice(t);
    vector< vector< modint > > dps(t.size());
    vector< int > buff(N), buff2(N, -1);

    MFP([&](auto rec, int idx) -> void {

      auto &ch = t[idx].child;
      auto &bag = t[idx].bag;

      for(auto &to : ch) rec(to);
      vector< modint > dp(1 << bag.size());

      if(ch.empty()) { // leaf
        dp[0] = 1;
      } else if(ch.size() == 2) { // join
        for(int i = 0; i < dp.size(); i++) {
          for(int j = 0; j < dp.size(); j++) {
            if((i & j) == 0) dp[i | j] += dps[ch[0]][i] * dps[ch[1]][j];
          }
        }
      } else {
        auto &ch_bag = t[ch[0]].bag;
        auto &ch_dp = dps[ch[0]];

        for(int i = 0; i < bag.size(); i++) {
          buff[bag[i]] = 1 << i;
          buff2[bag[i]] = idx;
        }

        if(ch_bag.size() + 1 == bag.size()) { // introduce
          for(int i = 0; i < ch_dp.size(); i++) {
            int bit = 0;
            for(int j = 0; j < ch_bag.size(); j++) {
              if((i >> j) & 1) bit |= buff[ch_bag[j]];
            }
            dp[bit] = ch_dp[i];
          }
        } else { // forgot
          int v = -1;
          for(int i = 0; i < ch_bag.size(); i++) {
            if(buff2[ch_bag[i]] != idx) v = ch_bag[i];
          }
          vector< int > ok_match(bag.size());
          for(int i = 0; i < bag.size(); i++) {
            ok_match[i] = edges.count(minmax(bag[i], v));
          }
          for(int i = 0; i < ch_dp.size(); i++) {
            int bit = 0;
            bool v_use = false;
            for(int j = 0; j < ch_bag.size(); j++) {
              if((i >> j) & 1) {
                if(v != ch_bag[j]) bit |= buff[ch_bag[j]];
              } else {
                if(v == ch_bag[j]) v_use = true;
              }
            }
            if(v_use) {
              for(int j = 0; j < bag.size(); j++) {
                if((bit >> j) & 1) continue;
                if(ok_match[j]) dp[bit | (1 << j)] += ch_dp[i];
              }
            } else {
              dp[bit] += ch_dp[i];
            }
          }
        }
      }
      dps[idx].swap(dp);
    })(root);
    auto &dp = dps[root];
    if(edges.count(minmax(t[root].bag[0], t[root].bag[1]))) dp.back() += dp[0];
    cout << dp.back() << endl;
  }
}
accuracy: 1
time_ms: 730
memory_kb: 52444
final_rank: 11

code_snippet: #include <bits/stdc++.h>

using namespace std;


using int64 = long long;
const int mod = 1000003;

const int64 infll = (1LL << 62) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;


template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 > &p) {
  os << p.first << " " << p.second;
  return os;
}

template< typename T1, typename T2 >
istream &operator>>(istream &is, pair< T1, T2 > &p) {
  is >> p.first >> p.second;
  return is;
}

template< typename T >
ostream &operator<<(ostream &os, const vector< T > &v) {
  for(int i = 0; i < (int) v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template< typename T >
istream &operator>>(istream &is, vector< T > &v) {
  for(T &in : v) is >> in;
  return is;
}

template< typename T1, typename T2 >
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template< typename T1, typename T2 >
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template< typename T = int64 >
vector< T > make_v(size_t a) {
  return vector< T >(a);
}

template< typename T, typename... Ts >
auto make_v(size_t a, Ts... ts) {
  return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...));
}

template< typename T, typename V >
typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {
  t = v;
}

template< typename T, typename V >
typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {
  for(auto &e : t) fill_v(e, v);
}

template< typename F >
struct FixPoint : F {
  FixPoint(F &&f) : F(forward< F >(f)) {}

  template< typename... Args >
  decltype(auto) operator()(Args &&... args) const {
    return F::operator()(*this, forward< Args >(args)...);
  }
};

template< typename F >
inline decltype(auto) MFP(F &&f) {
  return FixPoint< F >{forward< F >(f)};
}

struct DecompNode {
  vector< int > bag, child;

  DecompNode() = default;
};

struct TreeDecomposition {

  vector< vector< int > > g;

  explicit TreeDecomposition(int V) : g(V) {}

  void add_edge(int a, int b) {
    g[a].emplace_back(b);
    g[b].emplace_back(a);
  }

  vector< DecompNode > build() {
    const int N = (int) g.size();

    if(N <= 3) {
      DecompNode r;
      for(int i = 0; i < N; i++) r.bag.emplace_back(i);
      return {r};
    }

    vector< int > used(N, -1), deg(N);
    queue< int > que;
    for(int i = 0; i < N; i++) {
      deg[i] = (int) g[i].size();
      if(deg[i] == 2) que.emplace(i);
    }

    vector< set< int > > exists(N);
    for(int i = 0; i < N; i++) {
      for(auto &j : g[i]) {
        if(i < j) exists[i].emplace(j);
      }
    }

    vector< DecompNode > ret;
    while(!que.empty()) {
      int idx = que.front();
      que.pop();
      if(deg[idx] != 2 || used[idx] != -1) continue;

      DecompNode r;
      r.bag.emplace_back(idx);
      int u = -1, v = -1;
      for(auto &to : g[idx]) {
        if(used[to] == -1) {
          (u == -1 ? u : v) = to;
          r.bag.emplace_back(to);
        } else if(used[to] >= 0) {
          r.child.emplace_back(used[to]);
          used[to] = -2;
        }
      }

      if(u > v) swap(u, v);
      if(!exists[u].count(v)) {
        g[u].emplace_back(v);
        g[v].emplace_back(u);
        exists[u].emplace(v);
      } else {
        --deg[u];
        --deg[v];
      }

      for(auto &to : g[idx]) {
        if(deg[to] == 2) que.emplace(to);
      }

      used[idx] = (int) ret.size();
      deg[idx] = 0;
      ret.emplace_back(r);
    }

    DecompNode r;
    for(int i = 0; i < N; i++) {
      if(deg[i] == 1) r.bag.emplace_back(i);
    }
    if(r.bag.size() != 2) return {};
    for(auto &to : g[r.bag[0]]) {
      if(used[to] >= 0) {
        r.child.emplace_back(used[to]);
      }
    }
    ret.emplace_back(r);
    return ret;
  }
};


int to_nice(vector< DecompNode > &g, int root = -1) {
  if(root == -1) root = (int) g.size() - 1;

  for(auto &p : g) {
    sort(p.bag.begin(), p.bag.end());
  }

  stack< int > st;
  st.emplace(root);

  while(!st.empty()) {
    int idx = st.top();
    st.pop();

    // join
    while(g[idx].child.size() > 2) {
      DecompNode r;
      r.child.resize(2);
      r.child[0] = g[idx].child.back();
      g[idx].child.pop_back();
      r.child[1] = g[idx].child.back();
      g[idx].child.pop_back();
      r.bag = g[idx].bag;
      g[idx].child.emplace_back((int) g.size());
      g.emplace_back(r);
    }

    if(g[idx].child.size() == 2) {
      for(auto &ch : g[idx].child) {
        if(g[ch].bag != g[idx].bag) {
          DecompNode r;
          r.child.resize(1);
          r.child[0] = ch;
          r.bag = g[idx].bag;
          ch = (int) g.size();
          g.emplace_back(r);
        }
      }
    }

    // introduce / forgot
    if(g[idx].child.size() == 1) {
      int &ch = g[idx].child[0];

      vector< int > latte, malta;
      set_difference(g[idx].bag.begin(), g[idx].bag.end(),
                     g[ch].bag.begin(), g[ch].bag.end(),
                     back_inserter(latte));
      set_difference(g[ch].bag.begin(), g[ch].bag.end(),
                     g[idx].bag.begin(), g[idx].bag.end(),
                     back_inserter(malta));
      if(latte.size() + malta.size() > 1) {
        DecompNode r;
        r.child = {ch};
        r.bag = g[idx].bag;
        if(!latte.empty()) {
          r.bag.erase(find(r.bag.begin(), r.bag.end(), latte.back()));
        } else {
          r.bag.emplace_back(malta.back());
        }
        ch = (int) g.size();
        g.emplace_back(r);
      }
    }

    for(auto &ch : g[idx].child) {
      st.emplace(ch);
    }
  }
  return root;
}

template< int mod >
struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }

  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }

  static int get_mod() { return mod; }
};

using modint = ModInt< mod >;

int main() {
  int N, M;
  while(cin >> N >> M, N) {
    TreeDecomposition g(N);
    set< pair< int, int > > edges;
    for(int i = 0; i < M; i++) {
      int a, b;
      cin >> a >> b;
      --a, --b;
      edges.emplace(minmax(a, b));
      g.add_edge(a, b);
    }
    if(N == 3) {
      cout << 0 << endl;
      continue;
    }
    for(int i = 0; i < N; i++) {
      edges.emplace(minmax(i, (i + 1) % N));
      g.add_edge(i, (i + 1) % N);
    }
    auto t = g.build();
    int root = to_nice(t);
    vector< vector< modint > > dps(t.size());
    vector< int > buff(N), buff2(N, -1);

    MFP([&](auto rec, int idx) -> void {

      auto &ch = t[idx].child;
      auto &bag = t[idx].bag;

      for(auto &to : ch) rec(to);
      vector< modint > dp(1 << bag.size());

      if(ch.empty()) { // leaf
        dp[0] = 1;
      } else if(ch.size() == 2) { // join
        dp[0] = 1;
        for(auto &ch_dp : {dps[ch[0]], dps[ch[1]]}) {
          vector< modint > dp2(1 << bag.size(), 0);
          for(int i = 0; i < dp.size(); i++) {
            for(int j = 0; j < ch_dp.size(); j++) {
              if((i & j) == 0) dp2[i | j] += dp[i] * ch_dp[j];
            }
          }
          dp2.swap(dp);
        }
      } else {
        auto &ch_bag = t[ch[0]].bag;
        auto &ch_dp = dps[ch[0]];

        for(int i = 0; i < bag.size(); i++) {
          buff[bag[i]] = 1 << i;
          buff2[bag[i]] = idx;
        }

        if(ch_bag.size() + 1 == bag.size()) { // introduce
          for(int i = 0; i < ch_dp.size(); i++) {
            int bit = 0;
            for(int j = 0; j < ch_bag.size(); j++) {
              if((i >> j) & 1) bit |= buff[ch_bag[j]];
            }
            dp[bit] = ch_dp[i];
          }
        } else { // forgot
          int v = -1;
          for(int i = 0; i < ch_bag.size(); i++) {
            if(buff2[ch_bag[i]] != idx) v = ch_bag[i];
          }
          vector< int > ok_match(bag.size());
          for(int i = 0; i < bag.size(); i++) {
            ok_match[i] = edges.count(minmax(bag[i], v));
          }
          for(int i = 0; i < ch_dp.size(); i++) {
            int bit = 0;
            bool v_use = false;
            for(int j = 0; j < ch_bag.size(); j++) {
              if((i >> j) & 1) {
                if(v != ch_bag[j]) bit |= buff[ch_bag[j]];
              } else {
                if(v == ch_bag[j]) v_use = true;
              }
            }
            if(v_use) {
              for(int j = 0; j < bag.size(); j++) {
                if((bit >> j) & 1) continue;
                if(ok_match[j]) dp[bit | (1 << j)] += ch_dp[i];
              }
            } else {
              dp[bit] += ch_dp[i];
            }
          }
        }
      }
      dps[idx].swap(dp);
    })(root);
    auto &dp = dps[root];
    if(edges.count(minmax(t[root].bag[0], t[root].bag[1]))) dp.back() += dp[0];
    cout << dp.back() << endl;
  }
}
accuracy: 1
time_ms: 740
memory_kb: 57132
final_rank: 14