using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; class TEST{ static void Main(){ Sol mySol =new Sol(); mySol.Solve(); } } class Sol{ const long mod = (long) 1e9 + 7; public void Solve(){ var E = new MatMod(new long[][]{ new long[] {1, 0, 0, 0}, new long[] {0, 1, 0, 0}, new long[] {0, 0, 1, 0}, new long[] {0, 0, 0, 1} }); var ST = new SegTree(N, E, (a, b) => b * a ); var A = new MatMod(new long[][]{ new long[] {1, 0, 0, 0}, new long[] {0, 0, 0, 1}, new long[] {0, 0, 0, 1}, new long[] {0, 0, 0, 1} }); ST.UniqInit(A); long[] v0 = new long[] {1, 1, 1, 1}; for(int q=0;q= mod) vv %= mod; var aa = new MatMod(ST.At(i)); aa.A[1][1] = vv; aa.A[2][1] = 2*vv; aa.A[2][2] = vv*vv % mod; ST.Update(i,aa); break; case 'a': var xx = ST.Query(0,i); long ans = (xx * v0)[0]; Console.WriteLine(ans); break; default: break; } } } int N; int Q; String[][] Query; public Sol(){ N = ri(); Q = ri(); Query = new String[Q][]; for(int i=0;iint.Parse(e));} static long[] rla(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>long.Parse(e));} static double[] rda(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>double.Parse(e));} } struct MatMod{ public long[][] A; const long mod = (long)1e9+7; const int N = 4; public MatMod(long[][] a){ A = new long[N][]; for(int i=0;i= mod) A[i][j] %= mod; } } } public MatMod(MatMod a){ A = new long[N][]; for(int i=0;i= mod) c[i][j] %= mod; } } } return new MatMod(c); } static public long[] operator * (MatMod a, long[] v){ long[] c = new long[N]; for(int i=0;i= mod) c[i] %= mod; } } return c; } public override String ToString(){ return "{" + String.Join(" ",A.Select(ar => "[" + String.Join(" ",ar) + "]")) + "}"; } } class SegTree{ //segment Tree // 0-origin T[] Data; T Ini; Func Op; int N; int n; //コンストラクタ public SegTree(int n_,T ini_, Func op_){ N = n_; Ini = ini_; n = 1; while(n < n_) n *= 2; Data = new T[2*n - 1]; for(int i=0;i<2*n-1;i++) Data[i] = Ini; Op = op_; } //k-番目の値をaに変更 // 0 // 1 2 // 3 4 5 6 public void Update(int k,T a){ k += n-1; //上にはn-1個乗る Data[k] = a; while(k > 0){ k = (k-1) / 2; Data[k] = Op(Data[k*2+1],Data[k*2+2]); } } //Query; // [a,b) のOp(...)を返す // 後ろ3つの引数は k,l,r:ヒープのk-ノードが範囲 [l,r) に対応していることを示す // 外から呼ぶ時は Query(a,b,0,0,n) の形で呼ぶ public T Query(int a, int b){ return Query(a, b, 0, 0, n); } public T Query(int a,int b,int k,int l,int r){ // [a,b) ∩ [l,r) =φ ⇒Iniを返す if(r<=a || b<=l) return Ini; // [a,b) ⊃ [l,r) ⇒Data[k]を返す if(a<=l && r<=b)return Data[k]; // さもなくば、Op(l,r)を返す T vl = Query(a,b,k*2+1,l,(l+r)/2); T vr = Query(a,b,k*2+2,(l+r)/2,r); return Op(vl, vr); } public void UniqInit(T a){ for(int i=0;i=0;i--){ Data[i] = Op(Data[i*2+1], Data[i*2+2]); } } public void UniqUnit(T unit){ for(int i=0;i