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

struct tup
{
	int first; int second; int third;
};

tup seg[MAX];
int lazy[MAX];

void rotate(int i)
{
	int temp = seg[i].third;
	seg[i].third = seg[i].second;
	seg[i].second = seg[i].first;
	seg[i].first = temp;

}
void init(int node, int start, int end)
{
	if (start == end)
	{
		seg[node].first = 1; seg[node].second = 0; seg[node].third = 0;
		lazy[node] = 0;
	}
	else 
	{
		int mid = start + (end - start)/2;
		init(2*node + 1, start, mid);
		init(2*node + 2, mid + 1, end);
		seg[node].first = seg[2*node + 1].first + seg[2*node + 2].first;
		seg[node].second = 0; seg[node].third = 0;
		lazy[node] = 0;
	}
}

void updateRange(int node, int start, int end,int l,int r)
{
	int mid = start + (end - start)/2;
	if (lazy[node] != 0)
	{
		for(int i = 0; i < lazy[node]; i++)
			rotate(node);
		if (start != end)
		{
			lazy[2*node + 1] = (lazy[2*node + 1] + 1)%3;
			lazy[2*node + 2] = (lazy[2*node + 2] + 1)%3;
		}
		lazy[node] = 0;
	}
	if (start > end || start > r || end < l)
		return;
	else if (l == start && r == end)
	{
		rotate(node);
		if (start != end)
		{
			lazy[2*node + 1] = (lazy[2*node + 1] + 1)%3;
			lazy[2*node + 2] = (lazy[2*node + 2] + 1)%3;
		}
	}
	else
	{
		if (l >= start && r <= mid)
		{
			updateRange(2*node + 1, start, mid, l, r);
		}
		else if (l >= mid + 1 && r <= end)
		{
			updateRange(2*node + 2, mid + 1, end, l, r);
		}
		else
		{
			updateRange(2*node + 1, start, mid, l, mid);
			updateRange(2*node + 2, mid + 1, end, mid + 1, r);
		}
		seg[node].first = seg[2*node + 1].first + seg[2*node + 2].first;
		seg[node].second = seg[2*node + 1].second + seg[2*node + 2].second;
		seg[node].third = seg[2*node + 1].third + seg[2*node + 2].third;
	}
}

int query(int node, int start, int end, int l, int r)
{
	int mid = start + (end - start)/2;
	if (lazy[node] != 0)
	{
		for (int i = 0; i < lazy[node]; i++)
			rotate(node);
		if (start != end)
		{
			lazy[2*node + 1] = (lazy[2*node + 1] + 1)%3;
			lazy[2*node + 2] = (lazy[2*node + 2] + 1)%3;
		}
		lazy[node] = 0;
	}	
	if (start == l && end == r)
		return seg[node].first;
	else if (start <= l && r <= mid) /* First half */
		return query(2*node + 1, start, mid, l, r);
	else if (mid + 1 <= l &&  r <= end) /* Second half */
		return query(2*node + 2, mid + 1, end, l, r);
	else if (l >= start && r <= end)
		return query(2*node +1 , start, mid, l, mid) + query(2*node + 2, mid + 1, end, mid + 1, r);

}

int main()
{
	int n, q, t,x,y; scanf("%d%d", &n, &q);
	init(0, 0, n-1);
	for (int i = 0; i < q; i++)
	{
		scanf("%d%d%d", &t, &x, &y);
		if (t == 0)
			updateRange(0, 0, n-1, x, y);
		else
			printf("%d\n", query(0, 0, n - 1, x, y));
	}
	return (0);
}