Problem:
Sum of the Number of Triangles
We are given a rectangular region in the coordinate plane with the origin $O$ at the lower left and the point at coordinates $(W,H)$ at the upper right. Consider a collection of points in this region that contains at least three points whose $x$-coordinates and $y$-coordinates are both integers. Let $N$ be the number of combinations of all such point clusters.
  When each collection of points is represented by $D_1, D_2,...,D_N$, consider a triangle whose vertices are the points contained in $D_1, D2,...,D_N$.
For example, as shown in the figure, when $W=H=1$, there are five groups of points {O,A,B}, {O,A,C}, {O,B,C}, {A,B,C}, and {O,A,B,C} that contain three or more of the points O(0,0), A(1,0), B(1,1), and C(0,1). In this example, the triangles contained in each of the point clusters are as follows.
The only triangle contained in $\{O,A,B\}$ is $OAB$.
The only triangle contained in $\{O,A,C\}$ is $OAC$.
The only triangle contained in $\{O,B,C\}$ is $OBC$.
The only triangle contained in $\{A,B,C\}$ is $ABC$.
There are four triangles in	$\{O,A,B,C\}$: $OAB$, $OAC$, $OBC$, $ABC$.
As you can see from this example, the same triangle may be contained in more than one set of points. For example, triangle $OAB$ is contained in both the point set $\{O,A,B\}$ and $\{O,A,B,C\}$.
$W$ and $H$ are given. Let $t_1, t_2, ..., t_N$ be the number of triangles whose vertices are points in each of the point groups $D_1, D_2, ..., D_N$. Write a program to calculate the sum of the number of triangles $t_1+t_2+...+t_N$.
Input
The input is given in the following form.
$W$ $H$
$W$ and $H$ ($1 \leq W,H \leq 1,000$) are given in a line.
Output
Output the sum of the number of triangles in each set of points. Output the remainder divided by 1,000,000,007.
Sample Input and Output
Sample Input 1
1 1
Sample Output 1
8
Sample Input 2
1 2
Sample Output 2
144
Sample Input 3
100 100
Sample Output 3
879128399

Submitted solutions:

code_snippet: #include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef vector<vvll> vvvll;
typedef pair<int,int> pi;
typedef vector<string> vs;
typedef vector<char> vc;
typedef vector<vc> vvc;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define drep(i,a,n) for(int i=a;i>n;i--)
#define Yes(ans) {cout<<(ans?"Yes":"No")<<endl;}
#define printv(vec) {rep(iti_,0,vec.size()) cout<<vec[iti_]<<" "; cout<<endl;}
#define printvv(vec) {rep(ni_,0,vec.size()) printv(vec[ni_]); cout<<endl;}
#define all(x) x.begin(),x.end()
#define so(x) sort(all(x))
#define re(x) reverse(all(x))
template<typename T> bool chmin(T &a,T &b){if(a>b){a=b; return true;}return false;}
template<typename T> bool chmax(T &a,T &b){if(a<b){a=b; return true;}return false;}

int main(){
    ll m=1000000007;
    ll w,h; cin>>w>>h; w++; h++;
    ll n=w*h;
    ll ex=1; rep(i,0,n-3){ex*=2; ex%=m;}
    
    ll tri=n*(n-1)*(n-2)/6;
    ll per=w*h*(h-1)*(h-2)/6+h*w*(w-1)*(w-2)/6;
    ll na=0;
    rep(i,1,w+1){
        rep(j,1,h+1){
            if(gcd(i,j)!=1) continue;
            rep(k,2,100000){
                if(w-1-k*i<0||h-1-k*j<0) break;
                na+=(w-k*i)*(h-k*j)*(k-1);
            }
        }
    }
    //cout<<per<<" "<<na<<endl;
    tri-=per+2*na;
    //cout<<tri<<endl;
    tri%=m;
    //cout<<tri<<endl;
    ex*=tri;
    ex%=m;
    cout<<ex<<endl;
}
accuracy: 1
time_ms: 20
memory_kb: 3584
final_rank: 6

code_snippet: #include <bits/stdc++.h>
//#include"atcoder/all"
#define rep(i,n) for(int i=0;i<n;i++)
using namespace std;
//using namespace atcoder;
#define all(a) a.begin(),a.end()
#define int long long
typedef long long ll;
typedef vector<ll> vi;
typedef pair<int,int> P;
typedef pair<P,P> PP;
const int inf=1ll<<55;
const ll mod=1000000007;

int modpow(int a,int x){
	if(!x)return 1;
	int res=modpow(a*a%mod,x/2);
	if(x&1)res=res*a%mod;
	return res;
}
int gcd(int a,int b){
	if(!b)return a;
	return gcd(b,a%b);
}

signed main(){
	int h,w;cin>>h>>w;
	int ans=0;
	for(int i=1;i<=w;i++){
		for(int j=1;j<=h;j++){
			int x=4*(i-1)*(j-1)+2*(i+j-2)+4+2*((i+1)*(j+1)-4);
			int d=gcd(i,j);
			x-=2*(d-1);
			x*=(w-i+1)*(h-j+1);
			ans=(ans+x)%mod;

		}
	}
	
	ans=ans*modpow(2,(h+1)*(w+1)-3)%mod;
	cout<<ans<<endl;
}
accuracy: 1
time_ms: 50
memory_kb: 3440
final_rank: 9

code_snippet: #include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int Mod = 1e9 + 7;
ll bin_bow(ll a , ll b) {
	ll res = 1;
	while (b > 0) {
		if (b & 1)
			res = res * a % Mod;
		a = a * a % Mod;
		b >>= 1;
	}
	return res;
}
ll mod_inverse(ll a) {
	return bin_bow(a , Mod - 2);
}
int main(){
	ll w , h; cin>>w>>h;
	ll points = (w + 1) * (h + 1);

	ll all = points * (points - 1) % Mod * (points - 2) % Mod;
	all = all * mod_inverse(6) % Mod;
	ll Linear = 0;
	for(int i = 0;i <= h;i++) {
		for(int j = 0;j <= w;j++) {
			if(!i && !j)continue;
			ll temp = (h + 1 - i) * (w + 1 - j);
			temp %= Mod;
			if(i > 0 && j > 0)temp *= 2;
			temp *= __gcd(i , j)- 1;
			temp %= Mod;
			Linear += temp;
			Linear %= Mod;
		}
	}

	all -= Linear;
	all = (all + Mod) % Mod;
	cout<<(all * bin_bow(2LL , points - 3) % Mod)<<endl;
}
accuracy: 1
time_ms: 30
memory_kb: 3424
final_rank: 4

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }

template <int mod> struct static_modint {
    using mint = static_modint;
    int x;

    static_modint() : x(0) {}
    static_modint(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

    mint &operator+=(const mint &rhs) {
        if ((x += rhs.x) >= mod) x -= mod;
        return *this;
    }
    mint &operator-=(const mint &rhs) {
        if ((x += mod - rhs.x) >= mod) x -= mod;
        return *this;
    }
    mint &operator*=(const mint &rhs) {
        x = (int)(1LL * x * rhs.x % mod);
        return *this;
    }
    mint &operator/=(const mint &rhs) { return *this = *this * rhs.inv(); }

    mint pow(long long n) const {
        mint _x = *this, r = 1;
        while (n) {
            if (n & 1) r *= _x;
            _x *= _x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const { return pow(mod - 2); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }
    friend mint operator+(const mint &lhs, const mint &rhs) { return mint(lhs) += rhs; }
    friend mint operator-(const mint &lhs, const mint &rhs) { return mint(lhs) -= rhs; }
    friend mint operator*(const mint &lhs, const mint &rhs) { return mint(lhs) *= rhs; }
    friend mint operator/(const mint &lhs, const mint &rhs) { return mint(lhs) /= rhs; }
    friend bool operator==(const mint &lhs, const mint &rhs) { return lhs.x == rhs.x; }
    friend bool operator!=(const mint &lhs, const mint &rhs) { return lhs.x != rhs.x; }

    friend ostream &operator<<(ostream &os, const mint &p) { return os << p.x; }
    friend istream &operator>>(istream &is, mint &a) {
        int64_t t;
        is >> t;
        a = static_modint<mod>(t);
        return (is);
    }
};

const unsigned int mod = 1e9 + 7;
using modint = static_modint<mod>;
modint mod_pow(ll n, ll x) { return modint(n).pow(x); }
modint mod_pow(modint n, ll x) { return n.pow(x); }

template <typename T> struct Comination {
    vector<T> p, invp;

    Comination(int sz) : p(sz + 1), invp(sz + 1) {
        p[0] = 1;
        for (int i = 1; i <= sz; ++i) {
            p[i] = p[i - 1] * i;
        }
        invp[sz] = p[sz].inv();
        for (int i = sz - 1; i >= 0; --i) {
            invp[i] = invp[i + 1] * (i + 1);
        }
    }

    T comb(int n, int r) {
        if (r < 0 or n < r) return 0;
        return p[n] * invp[n - r] * invp[r];
    }
    T big_comb(T n, int r) {
        T res = invp[r];
        for (int i = 0; i < r; ++i) {
            res *= (n - i);
        }
        return res;
    }
};
using Comb = Comination<modint>;
Comb p(1002 * 1002);

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int h, w;
    cin >> h >> w;
    int al = (h + 1) * (w + 1);
    modint t = p.comb(al, 3);
    for (int i = 0; i <= h; ++i) {
        for (int j = 0; j <= w; ++j) {
            if (i + j == 0) continue;
            int g = gcd(i, j);
            modint line = max(0, g - 1);
            t -= line * (h + 1 - i) * (w + 1 - j) * ((i > 0 && j > 0) ? 2 : 1);
        }
    }
    cout << t * mod_pow(2, al - 3) << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 10836
final_rank: 11

code_snippet: #ifdef LOGX
#define _GLIBCXX_DEBUG
#endif
#include<bits/stdc++.h>
using namespace std;

using ll=long long;
#define rep(i,n) for(int i=0;i<int(n);i++)
#define rep2(i,s,n) for(int i=int(s);i<int(n);i++)
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
const int big=1e9+7;
//const int big=998244353;
const char newl='\n';
const int inf=1e9+10;
const ll INF=ll(1e18)+10;
const int dx[]={1,0,-1,0};
const int dy[]={0,1,0,-1};

using P=pair<ll,int>;
priority_queue<P,vector<P>,greater<P>> q;

struct mint{
    ll x;
    mint(ll xx=0):x(xx%big){
        if(x<0)x+=big;
    }
    mint& operator+=(mint r){
        x+=r.x;
        if(x>=big)x-=big;
        return *this;
    }
    friend mint operator+(mint l,mint r){
        return l+=r;
    }
    mint& operator-=(mint r){
        x-=r.x;
        if(x<0)x+=big;
        return *this;
    }
    friend mint operator-(mint l,mint r){
        return l-=r;
    }
    mint& operator*=(mint r){
        x*=r.x;
        x%=big;
        return *this;
    }
    friend mint operator*(mint l,mint r){
        return l*=r;
    }
};

template<typename T>
T exp(T x,ll y,T e){
    T res=e;
    while(y){
        if(y&1)res*=x;
        x*=x;
        y>>=1;
    }
    return res;
}

mint inv(mint x){
    assert(x.x!=0);
    return exp(x,big-2,mint(1));
}


int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(10);

    int H,W;
    cin >> H >> W;

    //dp[h][w]=([0,h],[0,w])から2点取ってきてad=bcの個数
    //重複とかは一旦気にしない！
    vector<vector<mint>> dp(H+1,vector<mint>(W+1));
    dp[0][0]=1;
    rep(h,H+1){
        //h/c(c<=h)の既約分数表示で、分子に現れる回数
        unordered_map<int,int> cnt;
        rep2(c,1,h+1)cnt[h/__gcd(c,h)]++;
        rep(w,W+1){
            if(h==0){
                dp[h][w]=mint(w+1)*(w+1);
                continue;
            }
            dp[h][w]=dp[h-1][w];
            //(a=h)+(c=h)-(a=c=h)
            //hd=bcを数える
            mint now=0;
            //d=0 -> (b=0)+(c=0)-(b=c=0)
            now+=(h+1)+(w+1)-1;
            
            //d!=0
            for(auto it:cnt){
                int val=it.first,num=it.second;
                now+=num*(w/val);
            }
            dp[h][w]+=2*now-(w+1);
        }
    }
    mint line=0;
    rep(i,H+1)rep(j,W+1){
        //原点以外から2点同じ点を選んだ場合
        dp[i][j]-=mint(i+1)*(j+1)-1;
        //原点から1点、原点以外からもう1点
        dp[i][j]-=2*(mint(i+1)*(j+1)-1);
        //原点から2点
        dp[i][j]-=1;
        dp[i][j]*=inv(mint(2));
    }
    rep(i,H+1)rep(j,W+1){
        line+=dp[i][j]+dp[H-i][j]-j*(j-1)/2-(H-i)*(H-i-1)/2;
    }

    ll hw_cnt=(H+1)*(W+1);
    mint ans=mint(hw_cnt)*(hw_cnt-1)*(hw_cnt-2)*inv(mint(3))*inv(mint(2))-line;
    cout << (ans*exp(mint(2),hw_cnt-3,mint(1))).x << newl;
}
accuracy: 1
time_ms: 140
memory_kb: 10892
final_rank: 14

code_snippet: #include <bits/stdc++.h>

using ll = long long;

template <class T> using Vec = std::vector<T>;

constexpr int MOD = 1000000007;

struct Fp {
    int x;
    Fp(int x = 0) : x(x) {}
    Fp operator+(const Fp& t) const { return Fp(*this) += t; }
    Fp& operator+=(const Fp& t) {
        if ((x += t.x) >= MOD) x -= MOD;
        return *this;
    }
    Fp operator-(const Fp& t) const { return Fp(*this) -= t; }
    Fp& operator-=(const Fp& t) {
        if ((x += MOD - t.x) >= MOD) x -= MOD;
        return *this;
    }
    Fp operator*(const Fp& t) const { return Fp((ll)x * t.x % MOD); }
    Fp& operator*=(const Fp& t) { return *this = *this * t; }
    Fp operator/(const Fp& t) const { return Fp(*this) /= t; }
    Fp& operator/=(const Fp& t) { return *this *= t.inv(); }
    Fp pow(ll e) const {
        Fp ret(1), mult(x);
        while (e > 0) {
            if (e & 1) ret *= mult;
            mult *= mult;
            e >>= 1;
        }
        return ret;
    }
    Fp inv() const { return pow(MOD - 2); }
};

Fp nCr(const int n, const int r) {
    Fp ret(1);
    for (int i = 0; i < r; ++i) {
        ret *= n - i;
        ret /= i + 1;
    }
    return ret;
}

int main() {
    int H, W;
    std::cin >> H >> W;
    H += 1, W += 1;
    Fp ans;
    ans += nCr(H * W, 3);
    ans -= nCr(H, 3) * W;
    ans -= nCr(W, 3) * H;
    for (int i = 1; i < H; ++i) {
        for (int j = 1; j < W; ++j) {
            ans -= (H - i) * (W - j) * 2 * (std::gcd(i, j) - 1);
        }
    }
    std::cout << (ans * Fp(2).pow(H * W - 3)).x << '\n';
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3440
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
template<class T> using vc = vector<T>;
template<class T> using vvc = vc<vc<T>>;
template<class T> using vvvc = vc<vvc<T>>;
template<class T> using vvvvc = vvc<vvc<T>>;
template<class T> using PQ = priority_queue<T>;
template<class T> using invPQ = priority_queue<T, vector<T>, greater<T>>;
using IP = pair<int, int>;
using LP = pair<ll, ll>;
#define all(x) begin(x), end(x)
#define allr(x) rbegin(x), rend(x)
#define rep(i, n) for (int i = 0; (i) < (int)(n); i++)
#define rep3(i, m, n) for (int i = (m); (i) < (int)(n); i++)
#define repr(i, n) for (int i = (n) - 1; (i) >= 0; i--)
#define rep3r(i, m, n) for (int i = (n) - 1; (i) >= (int)(m); i--)
template<class T> inline bool chmax(T & a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T & a, T b) { if (a > b) { a = b; return 1; } return 0; }
constexpr long long MOD = 1000000007;

long long gcd(long long a, long long b) {
    if (b == 0) return abs(a);
    return gcd(b, a % b);
}

ll comb3(ll n) {
    if (n < 3) return 0;
    return n * (n-1) * (n-2) / 6;
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    int W, H;
    cin >> W >> H;
    W++; H++;

    ll ans = 0;

    vvc<ll> s(W, vc<ll>(H));
    rep3 (a, 1, W) rep3 (b, 1, H) {
        s[a][b] = gcd(a, b) - 1;
    }
    rep3 (i, 1, W) rep3 (j, 1, H) {
        s[i][j] += s[i-1][j] + s[i][j-1] - s[i-1][j-1];
        s[i][j] %= MOD;
    }

    rep (i, W-1) rep (j, H-1) {
        ans += s[W - i - 1][H - j - 1];
        ans %= MOD;
    }

    ans = MOD*2 - ans*2;
    ans %= MOD;
    
    ans = (ans + comb3(H*W)) % MOD;
    ans = (ans - comb3(H) * W % MOD - comb3(W) * H % MOD + MOD*2) % MOD;

    rep (i, H*W-3) ans = (ans * 2) % MOD;

    cout << ans << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 10964
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
template<class T> using vc = vector<T>;
template<class T> using vvc = vc<vc<T>>;
template<class T> using vvvc = vc<vvc<T>>;
template<class T> using vvvvc = vvc<vvc<T>>;
template<class T> using PQ = priority_queue<T>;
template<class T> using invPQ = priority_queue<T, vector<T>, greater<T>>;
using IP = pair<int, int>;
using LP = pair<ll, ll>;
#define all(x) begin(x), end(x)
#define allr(x) rbegin(x), rend(x)
#define rep(i, n) for (int i = 0; (i) < (int)(n); i++)
#define rep3(i, m, n) for (int i = (m); (i) < (int)(n); i++)
#define repr(i, n) for (int i = (n) - 1; (i) >= 0; i--)
#define rep3r(i, m, n) for (int i = (n) - 1; (i) >= (int)(m); i--)
template<class T> inline bool chmax(T & a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T & a, T b) { if (a > b) { a = b; return 1; } return 0; }
constexpr long long MOD = 1000000007;

long long gcd(long long a, long long b) {
    if (b == 0) return abs(a);
    return gcd(b, a % b);
}

vector<long long> fac, finv, inv;
void COMinit(int N) {
    fac.resize(N+1, 1);
    finv.resize(N+1, 1);
    inv.resize(N+1, 1);
    for (int i = 2; i <= N; i++){
        fac[i] = fac[i - 1] * i % MOD;
        inv[i] = MOD - inv[MOD%i] * (MOD / i) % MOD;
        finv[i] = finv[i - 1] * inv[i] % MOD;
    }
}
long long COM(int n, int k){
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    int W, H;
    cin >> W >> H;
    W++; H++;

    COMinit(W*H);
    
    ll ans = COM(W*H, 3);
    ans = (ans - COM(W, 3) * H % MOD - COM(H, 3) * W % MOD + MOD * 2) % MOD;

    ll remcnt = 0;
    rep3 (a, 1, (H+1)/2) rep3 (b, 1, (W+1)/2) {
        if (gcd(a, b) != 1) continue;
        for (int i = 2; i*a < H && i*b < W; i++) {
            if ((i+1)*a >= H || (i+1)*b >= W) remcnt += COM(i+1, 3) * ((H - i*a) * (W - i*b));
            else if ((i+2)*a >= H || (i+2)*b >= W) remcnt += COM(i+1, 3) * ((H - i*a) * (W - i*b) - (H - (i+1)*a) * (W - (i+1)*b) * 2);
            else remcnt += COM(i+1, 3) * (a * b * 2);
            remcnt %= MOD;
        }
    }
    ans = (ans - remcnt*2 + MOD*2) % MOD;
    
    rep (i, H*W-3) ans = ans * 2 % MOD;
    cout << ans << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 26372
final_rank: 16

code_snippet: #include<cstdio>

long long q = 1000000007;

using namespace std;

int gcdf(int x, int y) {
    if(x % y == 0) {
        return y;
    } else {
        return gcdf(y, x % y); 
        //x%y==0でないときはユーグリットの互除法を使って再帰的に関数を呼び出す。
    }
}

long long modpow(long long a, long long n) {
    long long res = 1;
    while (n > 0) {
        if (n & 1) res = res * a % q;
        a = a * a % q;
        n >>= 1;
    }
    return res;
}


int main(){
	long long h,w,hw;
	long long a,b,per;
	
	
	scanf("%lld %lld",&h,&w);
	h++;
	w++;
	hw = h*w;
	long long liner1 = (h*w*( (w-1)*(w-2)+(h-1)*(h-2) )/6 )%q,liner2=0;
	long long h3=0,w3=0;
	for(int i=2;i<w;i++){
		for(int j=2;j<h;j++) {
			liner2 = ( liner2 + (gcdf(i,j)-1)*(w-i)*(h-j) )%q;
		}
	}
	liner2 = 2*liner2%q;
//	printf("%d %d\n",h,w);
//	printf("%lld %lld\n",liner1,liner2);
	
	long long liner = (liner1+liner2)%q;
	long long p3 = (hw*(hw-1))%q;
	p3 = (p3*(hw-2))%q;
	p3 = p3*modpow(6,q-2)%q;
//	printf("%lld\n",modpow(6,q-2));
	long long all = modpow(2,hw-3),ans = (all*((p3-liner+q)%q))%q;
//	printf("%lld * ( %lld - %lld )  = %lld\n",all,p3,liner,ans);
	printf("%lld\n",ans);
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 2764
final_rank: 1

code_snippet: #include<cstdio>

long long q = 1000000007;

using namespace std;

int gcdf(int x, int y) {
    if(x % y == 0) {
        return y;
    } else {
        return gcdf(y, x % y); 
        //x%y==0でないときはユーグリットの互除法を使って再帰的に関数を呼び出す。
    }
}

long long modpow(long long a, long long n) {
    long long res = 1;
    while (n > 0) {
        if (n & 1) res = res * a % q;
        a = a * a % q;
        n >>= 1;
    }
    return res;
}


int main(){
	int h,w,hw;
	long long a,b,per;
	
	
	scanf("%d %d",&h,&w);
	h++;
	w++;
	hw = h*w;
	long long liner1 = (h*w*( (w-1)*(w-2)+(h-1)*(h-2) )/6 )%q,liner2=0;
	long long h3=0,w3=0;
	for(int i=2;i<w;i++){
		for(int j=2;j<h;j++) {
			liner2 = ( liner2 + (gcdf(i,j)-1)*(w-i)*(h-j) )%q;
		}
	}
	liner2 = 2*liner2%q;
//	printf("%d %d\n",h,w);
//	printf("%I64d %I64d\n",liner1,liner2);
	
	long long liner = (liner1+liner2)%q;
	long long p3 = (hw*(hw-1))%q;
	p3 = (p3*(hw-2))%q;
	p3 = p3*modpow(6,q-2)%q;
//	printf("%I64d\n",modpow(6,q-2));
	long long all = modpow(2,hw-3),ans = (all*((p3-liner+q)%q))%q;
//	printf("%I64d * ( %I64d - %I64d )  = %I64d\n",all,p3,liner,ans);
	printf("%lld\n",ans);
	return 0;
}
accuracy: 0.6153846153846154
time_ms: 30
memory_kb: 2764
final_rank: 18

code_snippet: #line 1 "a.cpp"
#include<iostream>
#include<algorithm>
using namespace std;
#line 3 "/home/kotatsugame/library/math/modint.cpp"
#include<utility>
template<int m>
struct modint{
	unsigned int x;
	constexpr modint()noexcept:x(){}
	template<typename T>
	constexpr modint(T x_)noexcept:x((x_%=m)<0?x_+m:x_){}
	constexpr unsigned int val()const noexcept{return x;}
	constexpr modint&operator++()noexcept{if(++x==m)x=0;return*this;}
	constexpr modint&operator--()noexcept{if(x==0)x=m;--x;return*this;}
	constexpr modint operator++(int)noexcept{modint res=*this;++*this;return res;}
	constexpr modint operator--(int)noexcept{modint res=*this;--*this;return res;}
	constexpr modint&operator+=(const modint&a)noexcept{x+=a.x;if(x>=m)x-=m;return*this;}
	constexpr modint&operator-=(const modint&a)noexcept{if(x<a.x)x+=m;x-=a.x;return*this;}
	constexpr modint&operator*=(const modint&a)noexcept{x=(unsigned long long)x*a.x%m;return*this;}
	constexpr modint&operator/=(const modint&a)noexcept{return*this*=a.inv();}
	constexpr modint operator+()const noexcept{return*this;}
	constexpr modint operator-()const noexcept{return modint()-*this;}
	constexpr modint pow(long long n)const noexcept
	{
		if(n<0)return pow(-n).inv();
		modint x=*this,r=1;
		for(;n;x*=x,n>>=1)if(n&1)r*=x;
		return r;
	}
	constexpr modint inv()const noexcept
	{
		int s=x,t=m,x=1,u=0;
		while(t)
		{
			int k=s/t;
			s-=k*t;
			swap(s,t);
			x-=k*u;
			swap(x,u);
		}
		return modint(x);
	}
	friend constexpr modint operator+(const modint&a,const modint&b){return modint(a)+=b;}
	friend constexpr modint operator-(const modint&a,const modint&b){return modint(a)-=b;}
	friend constexpr modint operator*(const modint&a,const modint&b){return modint(a)*=b;}
	friend constexpr modint operator/(const modint&a,const modint&b){return modint(a)/=b;}
	friend constexpr bool operator==(const modint&a,const modint&b){return a.x==b.x;}
	friend constexpr bool operator!=(const modint&a,const modint&b){return a.x!=b.x;}
	friend ostream&operator<<(ostream&os,const modint&a){return os<<a.x;}
	friend istream&operator>>(istream&is,modint&a){long long v;is>>v;a=modint(v);return is;}
};
#line 5 "a.cpp"
using mint=modint<(int)1e9+7>;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int H,W;
mint F(int X){return mint(X+1)*X*(X-1);}
main()
{
	cin>>H>>W;
	int N=(H+1)*(W+1);
	mint ans=mint(N)*(N-1)*(N-2);
	ans-=mint(H+1)*F(W);
	ans-=mint(W+1)*F(H);
	mint diff=0;
	for(int i=1;i*2<=H;i++)for(int j=1;j*2<=W;j++)
	{
		if(gcd(i,j)!=1)continue;
		mint now=0;
		int ni=H%i+1,nj=W%j+1;
		int a=H/i,b=W/j;
		now+=mint(ni)*mint(nj)*F(min(a,b));
		now+=mint(i-ni)*mint(nj)*F(min(a-1,b));
		now+=mint(ni)*mint(j-nj)*F(min(a,b-1));
		now+=mint(i-ni)*mint(j-nj)*F(min(a-1,b-1));
		for(int x=i;x+i*2<=H;x++)
		{
			int na=(H-x)/i;
			now+=mint(nj)*F(min(na,b));
			now+=mint(j-nj)*F(min(na,b-1));
		}
		for(int y=j;y+j*2<=W;y++)
		{
			int nb=(W-y)/j;
			now+=mint(ni)*F(min(a,nb));
			now+=mint(i-ni)*F(min(a-1,nb));
		}
		diff+=now;
	}
	ans-=diff*2;
	ans/=6;
	cout<<ans*mint(2).pow(N-3)<<endl;
}
accuracy: 1
time_ms: 1930
memory_kb: 3120
final_rank: 17

code_snippet: #include<bits/stdc++.h>
#include<array>
using namespace std;
using LL = long long;
using ULL = unsigned long long;
#define rep(i,n) for(int i=0; i<(n); i++)

const ULL M = 1000000007;
const ULL inv6 = 166666668;
ULL SC[1002] = {};
ULL X[1002][1002] = {};

ULL GCD(ULL a, ULL b) { return b ? GCD(b, a % b) : a; }
ULL C3(ULL n) { return n * (n - 1) % M * (n - 2) % M * inv6 % M; }

int main() {
    int W, H; cin >> W >> H;
    for (ULL i = 3; i <= 1001; i++) SC[i] = (SC[i - 1] + C3(i)) % M;
    rep(x, W + 1) rep(y, H + 1) {
        X[x][y] = 2 * SC[min(x, y) + 1] + (abs(x - y) - 1) * C3(min(x, y) + 1);
        X[x][y] %= M;
        X[x][y] = X[x][y] * 2 % M;
    }

    ULL Tri = 0;
    Tri += (W + 1) * C3(H + 1) % M;
    Tri += (H + 1) * C3(W + 1) % M;
    for (ULL x = 1; x <= W; x++) for (ULL y = 1; y <= H; y++) {
        if (GCD(x, y) != 1) continue;
        ULL nx = W / x, ny = H / y;
        ULL mx = W % x + 1, my = H % y + 1;
        ULL tmp = 0;
        tmp += mx * my * X[nx][ny] % M;
        tmp += mx * (y - my) * X[nx][ny - 1] % M;
        tmp += (x - mx) * my * X[nx - 1][ny] % M;
        tmp += (x - mx) * (y - my) * X[nx - 1][ny - 1] % M;
        tmp %= M;
        Tri += tmp;
    }
    Tri %= M;
    
    ULL N = (H + 1) * (W + 1);
    ULL ans = C3(N) + M - Tri;
    rep(i, N - 3) ans = ans * 2 % M;
    cout << ans << endl;

    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 10944
final_rank: 13

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



ll W,H;
ll inv_6;

ll extgcd(ll a,ll b,ll &x,ll &y){
	ll d = a;
	if(b != 0){
		d = extgcd(b,a%b,y,x);
		y -= (a/b)*x;
	}else{
		x = 1;
		y = 0;
	}
	return d;
}

ll mod_inverse(ll a,ll m){
    ll x,y;
    extgcd(a,m,x,y);
    return (m+x%m)%m;
}

ll gcd(ll x,ll y){

	x = abs(x);
	y = abs(y);

	if(x < y){
		swap(x,y);
	}
	if(y == 0){
		return x;
	}else{
		return gcd(y,x%y);
	}
}

ll mod_pow(ll x,ll count, ll mod){

	if(count == 0)return 1;
	ll ret = mod_pow((x*x)%mod,count/2,mod);
	if(count%2 == 1){

		ret = (ret*x)%mod;
	}
	return ret;
}


ll numC3(ll num){

	if(num <= 2)return 0;

	ll ret = num;

	ret *= num-1;
	ret %= MOD;
	ret *= num-2;
	ret %= MOD;
	ret *= inv_6;
	ret %= MOD;

	return ret;
}

//https://betrue12.hateblo.jp/entry/2020/05/02/163444

int main(){

	inv_6 = mod_inverse(6,MOD);

	scanf("%lld %lld",&W,&H);

	ll N = (W+1)*(H+1);
	ll mult = mod_pow(2,N-3,MOD);

	ll base = numC3(N);

	ll minus = 0;

	for(ll i = 0; i <= H; i++){
		for(ll k = 0; k <= W; k++){
			if(i ==0 && k == 0)continue;

			ll tmp = (H+1-i)*(W+1-k);
			tmp %= MOD;

			if(i > 0 && k > 0){
				tmp *= 2;
				tmp %= MOD;
			}

			tmp *= gcd(i,k)-1;
			tmp %= MOD;

			minus += tmp;
			minus %= MOD;
		}
	}

	base -= minus;
	if(base < 0){

		base += MOD;
	}

	ll ans = base*mult;
	ans %= MOD;

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3228
final_rank: 7

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



ll W,H;
ll inv_6;

ll extgcd(ll a,ll b,ll &x,ll &y){
	ll d = a;
	if(b != 0){
		d = extgcd(b,a%b,y,x);
		y -= (a/b)*x;
	}else{
		x = 1;
		y = 0;
	}
	return d;
}

ll mod_inverse(ll a,ll m){
    ll x,y;
    extgcd(a,m,x,y);
    return (m+x%m)%m;
}

ll gcd(ll x,ll y){

	x = abs(x);
	y = abs(y);

	if(x < y){
		swap(x,y);
	}
	if(y == 0){
		return x;
	}else{
		return gcd(y,x%y);
	}
}

ll mod_pow(ll x,ll count, ll mod){

	if(count == 0)return 1;
	ll ret = mod_pow((x*x)%mod,count/2,mod);
	if(count%2 == 1){

		ret = (ret*x)%mod;
	}
	return ret;
}


ll numC3(ll num){

	if(num <= 2)return 0;

	ll ret = num;

	ret *= num-1;
	ret %= MOD;
	ret *= num-2;
	ret %= MOD;
	ret *= inv_6;
	ret %= MOD;

	return ret;
}

int main(){

	inv_6 = mod_inverse(6,MOD);

	scanf("%lld %lld",&W,&H);

	ll N = (W+1)*(H+1);
	ll mult = mod_pow(2,N-3,MOD);

	ll base = numC3(N);

	ll minus = 0;

	for(ll i = 0; i <= H; i++){
		for(ll k = 0; k <= W; k++){
			if(i ==0 && k == 0)continue;

			ll tmp = (H+1-i)*(W+1-k);
			tmp %= MOD;

			if(i > 0 && k > 0){
				tmp *= 2;
				tmp %= MOD;
			}

			tmp *= gcd(i,k)-1;
			tmp %= MOD;

			minus += tmp;
			minus %= MOD;
		}
	}

	base -= minus;
	if(base < 0){

		base += MOD;
	}

	ll ans = base*mult;
	ans %= MOD;

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3228
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int64_t MOD = 1e9+7;
void add(int64_t& a, int64_t b){
    a = (a+b) % MOD;
}
void mul(int64_t& a, int64_t b){
    a = a*b % MOD;
}

int64_t power_mod(int64_t num, int64_t power){
    int64_t prod = 1;
    num %= MOD;
    while(power > 0){
        if(power&1) prod = prod * num % MOD;
        num = num * num % MOD;
        power >>= 1;
    }
    return prod;
}

int64_t extgcd(int64_t a, int64_t b, int64_t& x, int64_t& y){
    int64_t d = a;
    if(b != 0){
        d = extgcd(b, a%b, y, x);
        y -= (a/b) * x;
    }else{
        x = 1; y = 0;
    }
    return d;
}

int64_t inv_mod(int64_t a){
    int64_t x, y;
    extgcd(a, MOD, x, y);
    return (MOD + x%MOD) % MOD;
}

vector<int64_t> fact, fact_inv;

void create_mod_tables(int num){
    fact.assign(num+1, 1);
    fact_inv.assign(num+1, 1);
    for(int i=1; i<=num; i++) fact[i] = fact[i-1] * i % MOD;
    fact_inv[num] = inv_mod(fact[num]);
    for(int i=num; i>0; i--) fact_inv[i-1] = fact_inv[i] * i % MOD;
}

int64_t comb_mod(int n, int k){
    return fact[n] * fact_inv[n-k] % MOD * fact_inv[k] % MOD;
}

int64_t perm_mod(int n, int k){
    return fact[n] * fact_inv[n-k] % MOD;
}

int64_t gcd(int64_t a, int64_t b){
    return b==0 ? a : gcd(b, a%b);
}

int main(){
    int H, W;
    cin >> H >> W;
    int N = (H+1)*(W+1);
    create_mod_tables(N);

    // 1直線に並ぶ3点を数える
    int64_t L = 0;
    
    // 両端のxとyの距離を全探索
    for(int i=0; i<=H; i++) for(int j=0; j<=W; j++){
        if(i == 0 && j == 0) continue;
        
        // 両端の取り方、i > 0 かつ j > 0 のときは反転も考慮
        int64_t res = (H+1-i) * (W+1-j);
        if(i > 0 && j > 0) mul(res, 2);
        // 間に取れる格子点の個数
        mul(res, gcd(i, j)-1);

        add(L, res);
    }

    // 1直線に並ばない3点
    int64_t ans = comb_mod(N, 3) - L + MOD;
    // 集合の選び方
    mul(ans, power_mod(2, N-3));

    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 18320
final_rank: 15

code_snippet: #include <bits/stdc++.h>

int ri() {
	int n;
	scanf("%d", &n);
	return n;
}

int gcd(int i, int j) {
	while (i && j) {
		if (i > j) i %= j;
		else j %= i;
	}
	return i + j;
}

#define MOD 1000000007
int main() {
	int h = ri() + 1, w = ri() + 1;
	int all = h * w;
	int res = (int64_t) all * (all - 1) * (all - 2) / 6 % MOD;
	
	for (int i = 0; i < h; i++) {
		for (int j = 0; j < w; j++) {
			if (!i && !j) continue;
			res -= (int64_t) (h - i) * (w - j) % MOD * (gcd(i, j) - 1) * (i && j ? 2 : 1) % MOD;
			if (res < 0) res += MOD;
		}
	}
	for (int i = 0; i < all - 3; i++) res = res * 2 % MOD;
	std::cout << res << std::endl;
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3244
final_rank: 3

code_snippet: #include <iostream>
#include <vector>
#include <array>
#include <list>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <tuple>
#include <bitset>
#include <memory>
#include <cmath>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <numeric>
#include <climits>
#include <cfloat>
#include <cassert>
#include <random>

constexpr long long int MOD = 1000000007;
long long int power(long long int base, long long int exp) {
	switch (exp) {
	case 0: return 1L;
	case 1: return base % MOD;
	default: return power(base, exp % 2) * power(base * base % MOD, exp / 2) % MOD;
	}
}
int gcd(int a, int b) {
	return b == 0 ? a : gcd(b, a % b);
}
int main() {
	long long int w, h; std::cin >> w >> h;
	const long long int point = (w + 1) * (h + 1);
	const long long int sum = point * (point - 1) % MOD * (point - 2) % MOD * power(6, MOD - 2) % MOD;
	long long int minus = 0;
	for (auto i = 0; i <= w; ++i) for (auto j = 0; j <= h; ++j) if (i != 0 || j != 0) {
		const auto count = (w - i + 1) * (h - j + 1);
		minus += (gcd(i, j) - 1) * count % MOD * ((i == 0 || j == 0) ? 1 : 2);
		minus %= MOD;
	}
	std::cout << ((sum - minus) % MOD + MOD) * power(2, point - 3) % MOD << '\n';
}
accuracy: 1
time_ms: 30
memory_kb: 3124
final_rank: 2

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}


template<typename T,T MOD = 1000000007>
struct Mint{
  static constexpr T mod = MOD;
  T v;
  Mint():v(0){}
  Mint(signed v):v(v){}
  Mint(long long t){v=t%MOD;if(v<0) v+=MOD;}

  Mint pow(long long k){
    Mint res(1),tmp(v);
    while(k){
      if(k&1) res*=tmp;
      tmp*=tmp;
      k>>=1;
    }
    return res;
  }

  static Mint add_identity(){return Mint(0);}
  static Mint mul_identity(){return Mint(1);}

  Mint inv(){return pow(MOD-2);}

  Mint& operator+=(Mint a){v+=a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator-=(Mint a){v+=MOD-a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator*=(Mint a){v=1LL*v*a.v%MOD;return *this;}
  Mint& operator/=(Mint a){return (*this)*=a.inv();}

  Mint operator+(Mint a) const{return Mint(v)+=a;}
  Mint operator-(Mint a) const{return Mint(v)-=a;}
  Mint operator*(Mint a) const{return Mint(v)*=a;}
  Mint operator/(Mint a) const{return Mint(v)/=a;}

  Mint operator-() const{return v?Mint(MOD-v):Mint(v);}

  bool operator==(const Mint a)const{return v==a.v;}
  bool operator!=(const Mint a)const{return v!=a.v;}
  bool operator <(const Mint a)const{return v <a.v;}

  static Mint comb(long long n,int k){
    Mint num(1),dom(1);
    for(int i=0;i<k;i++){
      num*=Mint(n-i);
      dom*=Mint(i+1);
    }
    return num/dom;
  }
};
template<typename T,T MOD> constexpr T Mint<T, MOD>::mod;
template<typename T,T MOD>
ostream& operator<<(ostream &os,Mint<T, MOD> m){os<<m.v;return os;}

//INSERT ABOVE HERE
using M = Mint<int>;
const int MAX = 1010;
int dp[MAX][MAX];
M sm[MAX][MAX]={};

signed main(){
  int h,w;
  cin>>h>>w;
  h++;w++;

  for(int i=0;i<MAX;i++)
    dp[0][i]=dp[i][0]=i;

  for(int i=1;i<MAX;i++)
    for(int j=1;j<MAX;j++)
      dp[i][j]=dp[min(i,j)][min(i%j,j%i)];

  for(int i=1;i<MAX;i++)
    for(int j=1;j<MAX;j++)
      sm[i][j]=sm[i][j-1]+M(dp[i][j]-1);

  for(int i=1;i<MAX;i++)
    for(int j=1;j<MAX;j++)
      sm[i][j]+=sm[i-1][j];

  int num=h*w;
  M ans=M(num)*M(num-1)*M(num-2)/M(6);
  //cout<<ans<<endl;

  for(int i=1;i<h;i++)
    for(int j=1;j<w;j++)
      ans-=M(2)*sm[i][j];
  //cout<<ans<<endl;

  ans-=M(h)*M(h-1)*M(h-2)/M(6)*M(w);
  ans-=M(w)*M(w-1)*M(w-2)/M(6)*M(h);
  //cout<<ans<<endl;

  ans*=M(2).pow(num-3);
  cout<<ans<<endl;
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 11092
final_rank: 10