开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 23 天,点击查看活动详情
Problem - 1333C - Codeforces 前缀和
自己想的是把不好的数组全找出来一减就可以了,但发现有点复杂,之后发现已经过了很长时间了,就去看题解了,,,
直接去找好的数组就可以,可以发现遍历到i时,以i为新数组的右端点,前面和为0区间的最大的左端点作为新数组的左端点maxl,可以发现这个左端点maxl+1到i区间和为0,然后数组个数就是i-(maxl+1)+1-1,减1是为了把maxl+1减掉,因为加上这个区间和就是0了,如果sum这个值之前出现过那么就看看maxl是否还满足是前面和为0区间的最大的左端点,不是就更新成最大值,一开始maxl=-1是为了符合初始的情况
C. Eugene and an array (区间为0前缀和处理)__Rikka_的博客-CSDN博客
int n,a[200005];
map<int,int>mp;
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
cin>>n;
int sum=0,ans=0,maxl=-1;
mp[0]=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
if(mp[sum]||sum==0)
{
maxl=max(maxl,mp[sum]);
}
ans+=i-maxl-1;
mp[sum]=i;
}
cout<<ans<<endl;
return 0;
}
//
Counting Arrays
可以求出不符合条件的个数然后用总数减去就可以,可以发现每个序列都一定至少会有一种,这种就是每次都选位置1,考虑别的情况,可以发现对于每一个a[i]和任意的j属于[2,n],都有gcd(a[i],j)>1的话就是不符合情况的,那么a[i]就需要是2~n中质数的乘积的倍数才可以,那这个种数是好求的,对于1个数k,他的倍数就是,对于每一个i所能选的数也就确定了,之后累加起来用总数减去就是答案,因为要的是下取整的结果所以m/k直接算就可以不用取模了(为了这玩意看了快一个小时,,)
Educational Codeforces Round 138 (Rated for Div. 2) A - E - 知乎 (zhihu.com)
int pri[1000006],cnt,n,m;
bool ispri[1000006];
void is_pri(int n)
{
memset(ispri,1,sizeof(ispri));
for(int i=2;i<=n;i++)
{
if(ispri[i]) pri[++cnt]=i;
for(int j=1;j<=cnt&&i*pri[j]<=n;j++)
{
ispri[i*pri[j]]=0;
if(i%pri[j]==0) break;
}
}
}
signed main()
{
//ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
cin>>n>>m;
is_pri(1000000);
int mul=1,ans=0,lcm=1;
for(int i=1;i<=n;i++)
{
if(ispri[i]) lcm=lcm*i;
if(lcm>m) break;
int tmp=m/lcm%mod;
mul=mul*tmp%mod;
ans=(ans+mul)%mod;
}
int poww=1,res=0;m%=mod;
for(int i=1;i<=n;i++)
{
poww=poww*m%mod;
res=(res+poww)%mod;
}
ans=(res-ans+mod)%mod;
cout<<ans<<endl;
return 0;
}
//