这个题的题目真的很恼火》。。。。。。。
简单解释一下,就是输入n和m,先求一个数列x[],x[i]表示i%m的值;然后又用一个数组s[],s[i]表示从x[i]起往前数,有多少个连续的不大于x[i]的数(包括x[i]自己)。然后求s[]所有元素和对m取余的结果。(n,m<=100000)
其实我们马上就可以想到,不需要存那么多的数:每次用i减去x[i]往后找第一个出现的大于x[i]的数的下标就是s[i],这样就可以维护一个单调递减的栈,每次新元素入队,就把栈顶及以后所有不大于x[i]的数扔出去就可以了;每次s[i]=stack[top].xiabiao-stack[top-1].xiabiao(这么写应该看得懂吧。。。。)。
如果你把所有s[i]加起来在对m取模,那你就要开long long(100000*100000,int君表示无力);如果你边加边取模就不用了。
<span style="font-size:18px;color:#ffffff;background-color: rgb(0, 0, 0);">#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int prime[100010],k=1;
bool p[1300010];
int t,n,m;
int stack[100010],top=0;
int is[100010];
int main()
{
memset(p,true,sizeof(p));
prime[k]=2;
for(int i=3;;i+=2)
{
if(p[i]) prime[++k]=i;
for (int j=1,t;j<=k&&(t=prime[j]*i)<1300000;j++)
{
p[t]=false;
if(i%prime[j]==0) break;
}
if(k==100000) break;
}
int ans,q;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
top=0;
stack[top]=0x3f3f3f3f;is[top]=0;
ans=0;
for(int i=1;i<=n;i++)
{
q=prime[i]%m;
while(stack[top]<=q) top--;
stack[++top]=q;is[top]=i;
ans+=is[top]-is[top-1];
ans%=m;
}
printf("%d\n",ans);
}
return 0;
}</span>
不流失,不蒸发,一袋能顶两袋撒
;
没坷垃,我们怎么种庄稼!