#include <bits/stdc++.h>
#define db(x) cout<<x<<" "
#define db1(x) cout<<x<<'\n'
#define db2(x,y) cout<<x<<" "<<y<<'\n'
#define db3(x,y,z) cout<<x<<" "<<y<<" "<<z<<'\n'
#define rep(i,n) for(int i=0;i<(n);++i)
#define repA(i,a,n) for(int i=a;i<=(n);++i)
#define repD(i,a,n) for(int i=a;i>=(n);--i)
#define pair(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define vi vector<int>
#define pi pair<int,int>
#define vpi vector<pair<int,int>>
#define um unordered_map<int,int>
#define ff first
#define ss second
#define all(a) a.begin(),a.end()
#define mod 998244353
#define N 2e5+11
using namespace std;
using ll = long long int;
int dx[] = {0,1,0,-1};
int dy[] = {1,0,-1,0};

// ll Power(ll x,ll y,ll m){
    
//     // Base Case
//     if(y==0){
//         return 1;
//     }
//     //Recursive x^(y/2)
//     ll smallPower = Power(x,y/2,m);
//     smallPower %= m;
    
//     smallPower = (smallPower*smallPower)%m;
    
//     if(y&1){
//         return (x*smallPower)%m;
//     }
//     return smallPower;
    
    
// }

// class cmp{

//   public:

//   bool operator()(pair<ll,ll> &p1, pair<ll,ll> &p2) {

//       ll val1 = 2*p1.first;
//       ll val2 = 2*p2.first;

//       return min(val1,p1.second)-min(p1.first,p1.second)>min(val2,p2.second)-min(p2.first,p2.second);

//   }

// };



void solve(){

   
    
  ll n,m;
  cin>>n>>m;


  ll ans = 0;

  ans = (n*(n-1))/2;
  ans += (m*(m-1))/2;

  db1(ans);





}



int main(){

  
 int t=1;
 //cin>>t;

while(t--){
 solve();
  }

  
  



  return 0;
}

// #include<bits/stdc++.h>
// using namespace std;
// int n,k;
// int arr[100001] = {0};
// int BIT[100001] = {0};

// void update(int i,int n,int value){
    
//     while(i<=n){
//         BIT[i]+=value;
//         i+=(i&(-i));
//     }
    
    
// }

// int query(int i,int n){
    
//     int ans=0;
    
//     while(i>0){
//         ans+=BIT[i];
//         i-=(i&(-i));
//     }
    
//     return ans;
// }


// void buildTree(int *arr, int s, int e, int *tree , int index) {

//   if (s == e) {
//     tree[index] = query(s+1,n)-query(s+1-k+1,n);
//     return;
//   }

//   int mid = (s+e)/2;
//   //left_subtree
//   buildTree(arr,s,mid,tree,2*index);
//   //right_substree
//   buildTree(arr,mid+1,e,tree,2*index+1);

//   tree[index] = tree[2*index] + tree[2*index+1];


// }


// int query(int *tree, int s, int e, int qs, int qe, int index) {

//   //complete overlap
//   if (qs<=s && qe>=e) {
//     return tree[index];
//   }

//   // no overlap

//   if(s>qe || e<qs) {
//     return 0;
//   }

//   // partial overlap and update the current answer

//   int mid  = (s+e)/2;

//   int leftAns = query(tree,s,mid,qs,qe,2*index);
//   int rightAns = query(tree,mid+1,e,qs,qe,2*index+1);

//   return leftAns + rightAns;



// }

// void updateNode(int *tree, int s, int e, int updateIndex, int value,int index) {

//   // check out of bound-no overlap

//   if(updateIndex>e||updateIndex<s) {
//     return;
//   }

//   // leaf node -> pahuch gaye apan  node par

//   if(s==e) {
//     update(updateIndex+1,n,value);
//     tree[index] = query(updateIndex+1,n)-query(updateIndex+1-k+1,n);;
//     return;
//   }

//   // partial overlap

//   int mid = (s+e)/2;

//   // left
//   updateNode(tree,s,mid,updateIndex,value,2*index);
//   // right
//   updateNode(tree,mid+1,e,updateIndex,value,2*index+1);
//   // update node jo leaf me change ho kar araha hai
//   tree[index] = tree[2*index] + tree[2*index+1];

// }

// int main() {

//   int q;
//   cin>>n>>k>>q;

//   //int *arr = new int[n];

//   for (int i = 0; i<n; i++)
//   cin>>arr[i];

//   int *tree = new int [4*n+1];

//   for (int i = 0; i<n; i++)
//   update(i+1,n,arr[i]);
    
//   while (q>0) {
//     int type,l,r;
//     cin>>type>>l>>r;
//     l--;
//     r--;
//     if (type == 1) {
//       updateNode(tree, 0, n-1, l, r, 1);
//     }
//     else {
//       cout << query(tree, 0, n-1, l, r, 1)<<endl;
//     }
//     q--;
//   }



//   return 0;
// }

Measured memory_bytes: 256