五月个人赛-Easy to improve(大数据,找规律)

Problem: Easy to improve

Time limit: 1s     Mem limit: 64 MB     

Problem Description

There are n numbers in array a and a function f whose code is:


ans = 0;

for (int i = 0; i < n; i++) {

for (int j = i+1; j < n; j++) {

ans += pow (a[i]+a[j], 3);

ans %= 1000000007;

}

}

return ans;


JieBa said, it's easy to improve the time complexity. So what's the 

final answer (module 1000000007)?

Input

There are T groups of test data. The first line contains one positive integer T (1<=T<=100). 

For each test data : the first line contains a single integer n (2<=n<=100000),  next line contains n numbers: a[0] to a[n-1] (0<=a[i]<=100000).


Output

For each case, output the answer in one line.

Sample Input
221 233 4 5
Sample Output
271584
题意:

优化算法

ans = 0;

for (int i = 0; i < n; i++) {

for (int j = i+1; j < n; j++) {

ans += pow (a[i]+a[j], 3);

ans %= 1000000007;

}

}

return ans;


思路:

易知,计算每个数到之后每个数的立方和,与每个数到之前每个数的立方和,结果不变。

 设有a1, a2, a3, a4, a5, 计算到a5, 即计算 (a1 + a5)2 + (a2 + a5)2 + (a3 + a5)2 + (a4 + a5)2 把 a5整理出来就可以得到公式啦~


注意点:

1、灵活变换题目,发现从后往前与从前往后计算方法一样

2、大数据的处理,之前代码怎么也AC不了, 在循环中多加了好几个%mod 就可以了

3、熟练用typedef long long ll 将long long变为ll来做,可以加快做题速度。


改善:

  发现自己想复杂了,可以合并成(a1 + a2 +……+a5) * (a1 * a1 + a2 * a2 + a3 * a3 +……+a5*a5) 的。噗 ==。

把学长更优化的代码贴在了下面的下面了

#include <iostream>
#include<stdio.h>

#include <cstdio>
#include <cstring>
#include <math.h>
using namespace std;

typedef unsigned long long LL;
#define mm(a) memset((a), 0, sizeof(a))
LL a[110000];
LL tri[110000];
LL dou[110000];
LL sing[110000];
LL n;
const LL mod = 1e9 + 7;

LL ppow(LL n, LL m) {
	LL ans = 1;
	while (m) {
		if (m % 2) ans = (ans * n) % mod;
		n = n * n % mod;
		m /= 2;
	}
	return ans % mod;
}

LL fff() {
	LL ans = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = i + 1; j <= n; j++) {
			//ans += pow((a[i] + a[j]) % mod , 3);
			ans += ppow((a[i] + a[j]) % mod, 3);
			ans %= mod;
		}
	}
	return ans;
}


int main() {
//   freopen("1.txt", "r", stdin);
	LL T;
	cin >> T;
	while (T --) {
		mm(tri);
		mm(sing);
		mm(dou);
		mm(a);
		cin >> n;
		tri[0] = dou[0] = sing[0] = 0;
		for (int i = 1; i <= n; i ++) {
			cin >> a[i];
			tri[i] = ppow(a[i], 3) + tri[i - 1];
			dou[i] = ppow(a[i], 2) + dou[i - 1];
			sing[i] = a[i] + sing[i - 1];
			sing[i] %= mod;
		}
		LL ans = 0;
		for (int i = 2; i <= n; i++) {
			ans += ((i - 1) * ppow(a[i], 3)) % mod;
			ans += tri[i - 1] % mod;
			ans += (3 * a[i] % mod * dou[i - 1]) % mod;
			ans += (3 * a[i] % mod * a[i]  % mod * sing[i - 1]) % mod;
			ans %= mod;
		}
		cout << ans << endl;
		//cout << fff() << endl;
	}
	return 0;
}


#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const long long mod=1e9+7;
const int maxn=1e5+10;
long long a[maxn];
int n;
int main()
{
  int t;
  cin>>t;
  while (t--)
  {
      cin>>n;
      for (int i=0;i<n;i++) cin>>a[i];
      long long sum1=0,sum2=0,sum3=0;
      for (int i=0;i<n;i++)
      {
          sum1=(sum1+a[i])%mod;
          sum2=(sum2+a[i]*a[i])%mod;
          sum3=(sum3+a[i]*a[i]*a[i])%mod;
      }
      long long  res=(n-4)*sum3%mod;
      res%=mod;
      res+=3*sum2*sum1%mod;
      res%=mod;
      cout<<res<<endl;
  }
  return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值