/************************************************
┆  ┏┓　　　┏┓ ┆
┆┏┛┻━━━┛┻┓ ┆
┆┃　　　　　　　┃ ┆
┆┃　　　━　　　┃ ┆
┆┃　┳┛　┗┳　┃ ┆
┆┃　　　　　　　┃ ┆
┆┃　　　┻　　　┃ ┆
┆┗━┓　  　┏━┛ ┆
┆　　┃　  　┃　　┆　　　　　　
┆　　┃　  　┗━━━┓ ┆
┆　　┃　 AC代马 　　┣┓┆
┆　　┃　        　　┏┛┆
┆　　┗┓┓┏━┳┓┏┛ ┆
┆　　　┃┫┫　┃┫┫ ┆
┆　　　┗┻┛　┗┻┛ ┆
************************************************ */
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <string>
#include <sstream>
#include <cstdio>
#include <cstring>
#include<cctype>
#include <math.h>
#include <cmath>
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define lb long double
#define LINF 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define random(x) (rand()%x)
#define sgn(x) (fabs(x) < eps ? 0 : ((x) < 0 ? -1 : 1))
#define rep(i, a, b) for(int i=a;i<b;i++)
#define req(j, a, b) for(int j=a;j<b;j++)
#define mem(a, b) memset(a, b, sizeof(a))
#define PI 3.141592653589793
#define K 20

using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
const double eps =1e-14;
const double pi = acos(-1);
const ll mod = 1e9 + 7;
const int hash_mod = 19260817;

inline int read()
{
    int X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}

inline double dbread()
{
    double X=0,Y=1.0; int w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=X*10+(ch^48),ch=getchar();
    ch=getchar();//读入小数点
    while(isdigit(ch)) X+=(Y/=10)*(ch^48),ch=getchar();
    return w?-X:X;
}

inline void write(int x)
{
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
}

ll gcd(ll a,ll b)//辗转相除法（欧几里德算法）求最大公约数
{
    return b ? gcd(b,a%b) : a;
}
ll lcm(ll a,ll b)
{
    return a*b/gcd(a,b);//最小公倍数
}
ll q_pow(ll base, ll p)
{
    ll result = 1;
    while(p > 0)
    {
        if(p&1)
        {//此处等价于if(power%2==1)
            result = result * base % 1000;
        }
        p >>= 1;//此处等价于power=power/2
        base = (base * base) % 1000;
    }
    return result;
}

const int N = 250005;
int fri[N];

void  init()
{
    for(int i = 0; i <= N; i++)
        fri[i] = i;
}
int find(int a)		//查找根节点
{
    int tem1 = a,tem2;
    while(a != fri[a])
        a = fri[a];
    while(tem1 != a)
    {
        tem2 = fri[tem1];
        fri[tem1] = a;
        tem1 = tem2;
    }
    return a;
}
void Union(int a,int b)
{
    int fri_a = find(a);
    int fri_b = find(b);
    if(fri_a != fri_b)
    {
        fri[fri_a] = fri_b;
    }
    return ;
}

int eval(char c)
{
    if(c==' ')
        return 0;
    if(c=='\'')
        return 1;
    return c - 'A' + 2;
}

double pointSegDist(double cx, double cy, double px1, double py1, double px2, double py2)
{
    cx -= px1;
    px2 -= px1;
    cy -= py1;
    py2 -= py1;

    double len = sqrt(px2*px2 + py2*py2);
    double ux = px2 / (len * 1.0);
    double uy = py2/ (len * 1.0);
    uy = -uy;
    double nx = cx * ux - cy * uy;
    double ny = cx * uy + cy * ux;

    if(nx>=0 && nx <= len)
        return abs(ny);

    if(nx > len)
        nx -= len;
    return sqrt(nx*nx + ny*ny);
}

bool f(ll n)
{
    for(ll i=2;i<=n;i++)
    {
        if(n % (i * i) == 0)
            return false;
    }
    return true;
}

int a[maxn];

int p[maxn];

int ans[maxn];

vector<int> v;

int main()
{
    int n, m;
    cin >> n >> m;
    int res;

    res = ((n-1) * n) / 2 + m * (m - 1) / 2;
    cout << res << endl;
    return 0;
}


Measured memory_bytes: 256