济南学习 Day 3 T2 am

看程序写结果(program)
Time Limit:1000ms Memory Limit:64MB
题目描述
LYK 最近在准备 NOIP2017 的初赛,它最不擅长的就是看程序写结果了,因此它拼命地
在练习。
这次它拿到这样的一个程序:
Pascal:
readln(n);
for i:=1 to n do read(a[i]);
for i:=1 to n do for j:=1 to n do for k:=1 to n do for l:=1 to n do
if (a[i]=a[j]) and (a[i]<a[k]) and (a[k]=a[l]) then ans:=(ans+1) mod 1000000007;
writeln(ans);
C++:
scanf(“%d”,&n);
for (i=1; i<=n; i++) scanf(“%d”,&a[i]);
for (i=1; i<=n; i++) for (j=1; j<=n; j++) for (k=1; k<=n; k++) for (l=1; l<=n; l++)
if (a[i]==a[j] && a[i]<a[k] && a[k]==a[l]) ans=(ans+1)%1000000007;
printf(“%d\n”,ans);
LYK 知道了所有输入数据,它想知道这个程序运行下来会输出多少。
输入格式(program.in)
第一行一个数 n,第二行 n 个数,表示 ai。
输出格式(program.out)
一个数表示答案。
输入样例
4
1 1 3 3
输出样例
4
数据范围
对于 20%的数据 n<=50。
对于 40%的数据 n<=200。
对于 60%的数据 n<=2000。
对于 100%的数据 n<=100000,1<=ai<=1000000000。
其中均匀分布着 50%的数据不同的 ai 个数<=10,对于另外 50%的数据不同的 ai 个
数>=n/10。

首先说:直接粘贴代码20%的数据肯定没问题,连对拍的代码都给你了,这个题还是比较良心的,20分,关键是如何优化

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100010
using namespace std;
const int mo=1e9+;
long long sum[N],a[N],num[N],ans;
int n,x;
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
sort(a+,a+n+);
memset(num,,sizeof num );
for(int i=;i<=n;i++)
{
if(a[i]!=a[i-])
x++;
num[x]++;
}
for(int i=;i<=x;i++)
num[i]=(num[i]*num[i])%mo;
for(int i=;i<=x;i++)
sum[i]=sum[i-]+num[i];
for(int i=;i<x;i++)
ans=(ans+num[i]*(sum[x]-sum[i]))%mo;
printf("%d",ans);
return ;
}


思路:读入之后,首先sort一遍,相同的数字肯定挨在了一起,扫一遍,记录每种数字出现的次数(即它的个数)(接下来用len表示),每一个len都平方一边,并用sum记录len^2的

前缀和。对于第i种数字对于答案的贡献为leni*len(i+1)+leni*len(i+2)+....+leni*(lenx)

即leni*(sum[x]-sum[i]);

上一篇:正确计算linux系统内存使用率


下一篇:1093. Count PAT's (25)