银联高校极客挑战赛 初赛 第二场 码队弟弟的求和问题 (除法分块)

码队的弟弟遇到了一个求和的问题,码队跟他弟弟说,如果遇到解决不了的问题就来找他,现在问题来了;

给定n,m求(\sum_{i=1}^{n}\sum_{j=1}^{m}ij(n \mod i)(m\mod j)) \mod(10^{9}+7)

请你帮助码队的弟弟解决这个问题

输入格式

仅一行,包含两个整数n,m

输出格式

仅一行,一个整数,即答案

数据规模

10\leq n,m\leq 10^9

样例输入

10  10

样例输出

6561

 

把式子化简之后就是这样

由于需要求 平方数列的和,用c++写超long long,然后孱弱的我只好用了java大数

下面是Java代码  (附赠一个c++的爆long long 的代码哈哈哈)

(有了一楼的评论,小孱弱用了逆元之后,就不再需要Java大数了   (O(∩_∩)O))

 

#include <bits/stdc++.h>
#define ll long long
const int maxn = 1e6+5;
const ll mod = 1e9+7;
using namespace std;
ll ksm(ll a,ll b) {
    ll ans=1;
    while(b) {
        if(b&1) ans = ans * a %mod;
        a = a * a %mod;
        b>>=1;
    }
    return ans%mod;
}
ll cal(ll n) {
    ll L=1,R,ans=0;
    for(L=1;L<=n;L=R+1) {
        ll t = n/L;
        R = n/t;
        ll temp1 = (1+2*R)*(R+1)%mod*R%mod*ksm(6,mod-2)%mod;
        ll temp2 = (1+2*(L-1))*(L-1)%mod*L%mod*ksm(6,mod-2)%mod;
        temp1 = (temp1 - temp2 + mod) % mod;
        ans += ( temp1 % mod) * t;
        ans %= mod;
    }
    return ans % mod;
}
ll cal1(ll n) {
    return (n*(n+1)/2)%mod;
}
int main()
{
    cal(10);
    ll n,m;
    scanf("%lld%lld",&n,&m);
    ll an = cal(n);
    ll am = cal(m);
    ll ans1 = n*m%mod * cal1(n) %mod *cal1(m) %mod;
    ll ans2 = cal1(n)*n%mod * am%mod;
    ll ans3 = cal1(m)*m%mod * an%mod;
    ll ans4 = an * am %mod;
    ll ans  = (ans1-ans2+mod) % mod;
       ans  = (ans -ans3+mod) % mod;
       ans  = (ans +ans4) % mod;
    printf("%lld\n",ans%mod);
    return 0;
}

 

 

import java.math.BigInteger;
import java.util.BitSet;
import java.util.Scanner;

public class Main{ 
	static BigInteger mmm = BigInteger.valueOf(1000000007);
	static BigInteger mul(BigInteger R) {
		BigInteger temp = BigInteger.ONE;
		return (R.multiply(R.add(temp).multiply(temp.add(R.multiply(BigInteger.valueOf(2))))).divide(BigInteger.valueOf(6)));
	}
	static BigInteger cal(BigInteger n) {
		BigInteger L,R,ans,t,temp = BigInteger.ONE,temp1,temp2;
		ans = BigInteger.ZERO;
		for(L=temp;L.compareTo(n)<=0;L=R.add(temp)) {
			t = n.divide(L);
			R = n.divide(t);
			temp1 = mul(R);
			temp2 = mul(L.subtract(temp));
			temp1 = temp1.subtract(temp2);
			ans = ans.add(temp1.multiply(t)); 
	    }
	    return ans;
	} 
	static BigInteger cal1(BigInteger n) {
		return n.multiply(n.add(BigInteger.ONE)).divide(BigInteger.valueOf(2));
	}
	public static void main(String[] args) { 
		  Scanner cin = new Scanner(System.in);
		  BigInteger n, m,an,am,ans1,ans2,ans3,ans4,ans;
		  n = cin.nextBigInteger();
		  m = cin.nextBigInteger();  
		  an = cal(n);
		  am = cal(m); 
		  ans1 = n.multiply(m).multiply(cal1(n)).multiply(cal1(m));
		  ans2 = cal1(n).multiply(n).multiply(am);
		  ans3 = cal1(m).multiply(m).multiply(an);
		  ans4 = an.multiply(am);
		  ans = ans1.subtract(ans2);
		  ans =ans.subtract(ans3);
		  ans =ans.add(ans4);
		  System.out.println(ans.mod(mmm));
		  System.exit(0);
	} 
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值