//注意点:在判断浮点数是否等于一个数的时候不能if(x == y)
而是要判断它是否属于某一范围,或者二者差的绝对值属于某一范围一般取<0.01
最好用double,用float跟答案就差了几个数
#include <iostream>
#include <math.h>
using namespace std;
const double N=23333333;
const double S=11625907.5798;
int main()
{
//0出现的次数比1出现的次数少这句话非常重要!!!
//限制了0的数量不会超过23333333/2
for(int i=0;i<(int)N/2;i++){
int m=(int)N-i;
double ss=-i*(i/N)*log2(i/N)-(m)*(m/N)*log2(m/N);
if(abs(ss-S)<0.01)
{
cout<<i<<endl;
break;
}
}
return 0;
}
一说到连续区间的和就应该想到前缀和,求区间[L,R]内的和=s[r]-s[l-1]
前缀和下标必须从1开始
我只想说k倍区间这个题太坑了,还需要技巧,这个细节还多,不太好想
细节一:利用前缀和那几个连续区间求出在中间的那些k倍区间,就是余数相同的那些#区间可以两两相减,减出来的就是k倍区间,所以找到一个余数相同的就++,用cnt数组#记录下来,同时k倍区间的数要加上相同余数的所有区间的数,因为这一个数可以和所有区间两两结合,就生成cnt个k倍区间
细节二:cnt[0]=1;因为余数为0的本来就是一个k倍区间,可以假想为自己与自己相减
细节三:k倍区间的个数也需要用long long ,反正数量级别大的尽量都用LongLong吧
#include <iostream>
using namespace std;
const int N=1e5+10;
int n,k;
long long cnt=0;
long long a[N];
//没有想到前缀和,真的罪该万死呜呜呜呜
//不过就算用前缀和还是会超时,这题要用到一个技巧
//余数相同的两个值相减所得的区间就是k倍区间。
int sum[N];//记录余数相同的区间的个数
//中间的区间之和能整除k都是由两头区间的余数相同的区间相减得来的
int main()
{
sum[0]=1;//因为余数是0的话本身就是k倍区间,可以看做自身与自身减
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{ scanf("%d",&a[i]);
a[i]+=a[i-1];
cnt+=sum[a[i]%k];//只要有一个相同的就加原来所有相同的个数
//因为这个相同的可以跟之前所有相同的分别进行一次相减
sum[a[i]%k]++;
}//前缀和直接求到a[i]自己身上
cout<<cnt<<endl;
return 0;
}