#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define debug cerr << "-- " << __LINE__ << " --" << endl
#define MOD 1000000007
#define ALL(o) (o).begin(), (o).end()
typedef long long int ll;

using namespace std;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;
template <typename T> string to_string(const vector<T> &xs) {string s="["; for(int i=0;i<xs.size();i++) s += (i>0 ? " " : "") + to_string(xs[i]); return s + "]";}
template <typename T> ll argmax(const T &xs) {return distance(xs.begin(), max_element(xs.begin(), xs.end()));}
template <typename T> ll argmin(const T &xs) {return distance(xs.begin(), min_element(xs.begin(), xs.end()));}
ll nextLL(){ll x; scanf("%lld", &x); return x;}
int nextInt(){int x; scanf("%d", &x); return x;}
string nextString(){string s; cin >> s; return s;}


ll extgcd(ll a, ll b, ll &x, ll &y) {
    /* g を返す時点で ax + by == g となる */
    ll g = a; x = 1; y = 0;
    if (b != 0) g = extgcd(b, a % b, y, x), y -= (a / b) * x;
    return g;
}
ll gcd(ll a, ll b) { ll x, y; return extgcd(a, b, x, y); }
ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }

class llm{
	ll n;
public:
	llm(){n = 0;}
	llm(ll n){this->n = (n >= 0) ? (n % MOD) : (MOD - 1 - (-n-1 % MOD));}
	operator ll() const {return n;}
	llm operator+(const llm &y) const{ return llm((ll)*this + (ll)y);}
	llm operator+=(const llm &y) { *this = *this + y; return *this;}
	llm operator-(const llm &y) const{ return llm((ll)*this - (ll)y);}
	llm operator-=(const llm &y) { *this = *this - y; return *this;}
	llm operator-() const{ return llm(0) - *this;}
	llm operator*(const llm &y) const{ return llm((ll)*this * (ll)y);}
	llm operator*=(const llm &y) { *this = *this * y; return *this;}
	llm operator/(const llm &y) const{ return *this * y.inv();}
	llm operator/=(const llm &y) { *this = *this / y; return *this;}
	llm inv() const{
		ll x, y;
		if (extgcd(n, MOD, x, y) == 1) return llm(x);
  		return llm(0); // unsolvable
	}
	friend istream& operator >> (istream& os, llm& x);
	friend ostream& operator << (ostream& os, const llm& x);
};
istream& operator >> (istream& is, llm& x){ll n; is >> n; x = llm(n); return is;}
ostream& operator << (ostream& os, const llm& x){os << (ll)x; return os;}

template<typename T> T comb(ll n, ll k){
	T ret = 1;
	for(ll i=1;i<=k;i++) ret = ret * T(n - k + i) / T(i);
	return ret;
}


ll n, x, d;


vector<pair<ll, ll>> segmentUnion(vector<pair<ll, ll>> segments){
	/* 半開区間たちの和集合を求めます．O(n log n) */
	vector<pair<ll, ll>> ret;
	if (segments.empty()) return ret;
	sort(segments.begin(), segments.end());
	ll l = segments[0].first, r = segments[0].second;
	for(int i=1;i<segments.size();i++){
		if (r <= segments[i].first){
			ret.push_back(make_pair(l, r));
			l = segments[i].first; r = segments[i].second;
		}else{
			r = max(r, segments[i].second);
		}
	}
	ret.push_back(make_pair(l, r));
	return ret;
}

ll remainder(ll x, ll y) {assert(y > 0); ll r = x % y; if (r < 0) r += y; return r;}
ll quotient(ll x, ll y) {assert(y > 0); return (x - remainder(x, y)) / y;}


int main(void){
	cin >> n >> x >> d;
	// x, x+d, x+2d, ..., x+(n-1)d の部分和が何通りあるか．
	ll ans = 0;
	if (d < 0){
		x = x + (n-1) * d;
		d = -d;
	}

	if (d==0){
		// x, x, ..., x (n個)
		if (x != 0) ans = n + 1; else ans = 1;
	}else{
		/*
			n+1 個の等差数列となる 全て公差は d
			0
			x, x+d, x+2d, ..., x+(n-1)d
			2x+d, ..., 2x+(2n-3)d
			3x+3d, ..., 3x+(3n-6)d
			:
			:
			nx+(n-1)n/2*d
		*/
		map<ll, vector<pair<ll, ll>>> segmentList;
		ll start = 0, end = d;
		for(ll i=0;i<=n;i++){
			ll r = remainder(start, d);
			segmentList[r].pb(mp(quotient(start, d), quotient(end, d)));
			// cerr << r << "  [" << quotient(start, d) << " " << quotient(end, d) << "]" << endl;
			start += x + i * d;
			end += x + (n - 1 - i) * d;
		}
		for(auto kv : segmentList){
			auto v = kv.second;
			vector<pair<ll, ll>> uni = segmentUnion(v);
			for(auto seg : uni) ans += seg.second - seg.first;
		}
	}
	cout << ans << endl;
	
    return 0;
}




Measured memory_bytes: 22144