洛谷8月月赛

来源:互联网 发布:c语言机器人编程代码 编辑:程序博客网 时间:2024/04/30 09:15

T1 Problem A

题目描述

给定一个整数 n,求将 n 分解为互不相同的不小于 2 的数的乘积的方案数。答案模 998244353

输入输出格式
输入格式:

第一行一个整数 T,表示数据组数。

接下来 T 行,每行一个整数 n,意义如描述所述。

输出格式:

一共 T 行,每行一个整数,表示答案。

输入输出样例
输入样例#1:

1
688

输出样例#1:

6

说明

样例中,因为

688=2×4×86=2×8×43=2×344=4×172=8×86=16×43688

所以答案为 6

对于 10% 的数据,保证 n 为质数

对于 20% 的数据,保证 2n104

对于 50% 的数据,保证 2n107

对于 100% 的数据, 保证 2n1012

所有数据满足 1T5


呆滞的60分暴力,首先检查是不是质数,然后对是他因子的数进行枚举,非常朴素的暴力

#include<iostream>#include<cstdio>#include<cmath>#define ll long longusing namespace std;const int mod=998244353;ll x;int T;inline ll read(){    ll f=0;char c=getchar();    while(!isdigit(c))c=getchar();    while(isdigit(c))f=f*10+c-'0',c=getchar();    return f;}inline ll dfs(int x,ll sum){    if(sum==1)return 1;    ll s=0,d=sqrt(sum);    int flag=0;    for(register int i=x;i<=d;i++){        if(sum%i==0&&(sum>i*i))            s+=dfs(i+1,sum/i);    }    return s+1;}inline ll check(ll p){    ll d=sqrt(p);    for(register int i=2;i<=d;i++)        if(p%i==0) return 0;    return 1;}int main(){    T=read();    while(T--){        x=read();        if(check(x))            printf("0\n");        else             printf("%lld\n",(dfs(2,x)-1)%mod);    }    return 0;}

然后是孔爷的AC代码,大概就是一个hash+记忆化dp,而且还要注意要把因数都放入数组,这样可以大幅优化复杂度,本来枚举下一个因子的时间是O(n),现在变成了O(1)枚举,优化显而易见,具体的见我写的注释吧(话说孔爷实在是太强了,已经成为孔爷的小粉丝)

//我参考的孔爷代码……自己稍微修改了一下 #include<bits/stdc++.h>using namespace std;typedef long long ll;const int N=2e5+5,D=998244353;const ll U=1e12+5;int a[N];int top,T;ll n;namespace Hash{    //hash判重     const int T=1e7;    const int D=5780347;//大质数     int pre[D] ,val[T],next[T],tot;//首,dp值,后继,总数     ll  to[T];//hash值     int &get(const ll &x)//hash操作,用前向星完成链表     {        //从起点开始,像链的后端过去         for(int i=pre[x%D];i;i=next[i])            if(to[i]==x)return val[i];//如果匹配成功,就返回         to[++tot]=x;//存hash值         next[tot]=pre[x%D];//前向星连接         pre[x%D]=tot;        return val[tot];//返回地址     }};inline int DP(const ll &n,int h)//n是剩下的数,h是枚举的因子位置 {    if(h>top)        return 1;//超出因数范围     int x=a[h];    if(ll(x)*x>=n)        return 1;//剩下最小情况仍然大于现在分解数     int &ans=Hash::get(x*U+n);//ans<=>dp[n][x]    //记忆化     if(ans)        return ans;//有解就返回解     ans=DP(n,h+1);//不选     if(n%x==0)        (ans+=DP(n/x,h+1))%=D;//合法继续搜索     return ans;}int main(){    cin>>T;    while(T--)    {            ll n;        cin>>n;//读入         top=0;        int mi=sqrt(n);//分解到sqrt(n)即可,因为不可能有比 sqrt(n)更大的因数         for(int i=2;i<=mi;++i)            if(n%i==0)a[++top]=i;//分解因数         if(!top)puts("0");//质数情况         else cout<<DP(n,1)-1<<endl;//DP,从第一个因数分解n     }    return 0;}

T2 Problem B

题目描述

n 个点的无向完全图删去一条边之后圈的个数,答案模 998244353

注:圈指的是任选一个顶点为起点,沿着不重复的边,经过不重复的顶点为途径,之后又回到起点的闭合途径。

输入输出格式
输入格式:

第一行一个整数 T,表示数据组数。

接下来 T 行,每行一个整数 n,意义如描述所述。

输出格式:

一共 T 行,每行一个整数,表示答案。

输入输出样例
输入样例#1:

4
3
4
5
6

输出样例#1:

0
3
22
133

说明

10% 的数据满足 3n103

另外 20% 的数据满足 9.99×102n103

另外 30% 的数据满足 9.99×104n105

另外 40% 的数据满足 9.99×108n109

所有数据满足 1T10


T3 Problem C

题目描述

给定一个长度为 n 的序列,给出 q 个操作,形如:

1 l r x表示将序列下标介于 [l,r] 的元素加上 x(请注意,x 可能为负)

2 p y表示查询 ap​​ 在过去的多少秒时间内不小于 y (不包括这一秒,细节请参照样例)

开始时为第 0 秒,第 i 个操作发生在第 i 秒。

输入输出格式
输入格式:

第一行两个整数 n,q,意义如描述所述。

接下来一行 n个整数 ai,表示序列的每个元素的初始值。

接下来 q 行,每行第一个数为 opt,表示这次操作的类型。
如果opt=1,后面紧跟三个整数 l,r,x意义如描述所述;
如果opt=2,后面紧跟两个整数 p,y意义如描述所述。

输出格式:

对于每个操作 2,在一行内输出一个数表示答案。

输入输出样例
输入样例#1:

3 3
1 3 5
2 1 2
1 1 2 -3
2 1 1

输出样例#1:

0
2

说明

样例一说明:位置 1 在第 0 秒到第 3 秒的值为 1,1,2,2。对于第一个查询,前 11=0 秒中有 0 秒时间不小于 2;对于第二个查询,前 31=2 秒中有 2 秒时间不小于 1,分别为第 0 秒,第 1 秒。

对于 30% 的数据,保证 n,q1000

对于 70% 的数据,保证 n,q50000

对于 100% 的数据,保证 2n,q1000001lrn109x,y,ai109


先放上孔爷代码,明天过来打题解

#include<bits/stdc++.h>using namespace std;typedef long long ll;#define mid (l+r>>1)#define pb push_back#define rep(i,l,r) for(int i=l;i<=r;++i)#define per(i,r,l) for(int i=r;i>=l;--i)template <typename T> inline void chmin(T &x,const T &y){    if(x>y)x=y;}template <typename T> inline void chmax(T &x,const T &y){    if(x<y)x=y;}#define gc (c=getchar())int read(){    char c;    while(gc<'-');    if(c=='-')    {        int x=gc-'0';        while(gc>='0')x=x*10+c-'0';        return -x;    }    int x=c-'0';    while(gc>='0')x=x*10+c-'0';    return x;}const int N=1e5+5,K=340*3;int n,m;ll a[N];struct Query{    bool type;    int l,r,x;}query[N];int q2[N],ans[N],top;/*bool x_xiao(const Q2 &q1,const Q2 &q2){    return q1.x<q2.x;}bool id_xiao(const Q2 &q1,const Q2 &q2){    return q1.id<q2.id;}*/int suf[N];int belong[N];bool need[N];struct point{    ll x;int w;};bool x_da(const point &a1,const point &a2){    return a1.x>a2.x;}int nl,nr;struct Clock{int kl,kr;ll nx;point a[K+5];int top;inline void add(int x,int w){    ++top;    a[top]=(point){nx+=x,w};}void init(){    rep(i,0,top-1)a[i].w=a[i+1].w-a[i].w;    a[top].w=nr-a[top].w+1;     sort(a,a+top+1,x_da);    rep(i,1,top)a[i].w+=a[i-1].w;}/*int get2(const ll &x){    if(a[1].x<x) return 0;    if(a[top].x>=x) return a[top].w;    int l=1,r=top;    while(l+1!=r)    if(a[mid].x>=x) l=mid;    else r=mid;    return a[l].w;}*/}block[K];int k;int main(){//    freopen("1.in","r",stdin);freopen("1.out","w",stdout);    cin>>n>>m;    rep(i,1,n)a[i]=read();    rep(i,1,m)    if(read()==1)    {        query[i]=(Query){0,read(),read(),read()};    }    else    {        query[i]=(Query){1,read(),0,read()};        q2[++top]=i;        ans[i]=(a[query[i].l]>=query[i].x);    }    q2[top+1]=N;    int qh=1;    int L=sqrt(m-top+1);    //sort(q2+1,q2+top+1,x_xiao);    int i=1;    for(;i<=m;i=nr+1)    {        memset(need,0,sizeof(need));        nl=i;        int cnt=0;        for(;i<=m;++i)        if(query[i].type==0)        {            if(++cnt>L)break;           need[query[i].l]=1;           need[query[i].r+1]=1;        }        nr=i-1;        k=0;        rep(i,1,n)        {            if(need[i])            {               chmin(block[k].kr,i-1);               ++k;               block[k].kl=i;               block[k].kr=n;            }        }        memset(belong,0,sizeof(belong));        rep(i,1,k)        {            rep(j,block[i].kl,block[i].kr) belong[j]=i;            block[i].top=0;block[i].nx=block[i].a[0].x=0;            block[i].a[0].w=nl;        }        block[0].a[0].w=nl;        block[k+1].kl=block[k+1].kr=N;        rep(i,nl,nr)        if(query[i].type==0)        {             int l=belong[query[i].l],r=belong[query[i].r];             int nx=query[i].x;             for(;l<=r;++l)             {                 block[l].add(nx,i);             }        }        else        {            int l=query[i].l,b=belong[l];            //if(block[b].top)            {                point *p=block[b].a,*end=p+block[b].top;                ll qx=query[i].x-a[l];                while(p<end)                {                  if(p->x>=qx) ans[i]+=(p+1)->w-p->w;                  ++p;                }                   if(end->x>=qx)ans[i]+=i-end->w;            }        /*    else            if(a[l]>=query[i].x)             {                ans[i]+=i-nl;            }*/        }        rep(i,0,k) block[i].init();        while(q2[qh]<=nr)++qh;        rep(h,qh,top)        {            int i=q2[h],l=query[i].l;            int b=belong[l],r=block[b].top;        //    if(r)            {                ll qx=query[i].x-a[l];               point *a=block[b].a;               if(a->x<qx) continue;                   if((a+r)->x>=qx){ans[i]+=(a+r)->w;continue;}               int l=0;               while(l+1!=r)               if((a+mid)->x>=qx) l=mid;               else r=mid;               ans[i]+=(a+l)->w;            }        /*    else            {                if(a[l]>=query[i].x) ans[i]+=nr-nl+1;            }*/        }        rep(i,1,k)        {            ll nx=block[i].nx;            rep(j,block[i].kl,block[i].kr) a[j]+=nx;        }    }    //sort(q2+1,q2+top+1,id_xiao);    rep(i,1,top) printf("%d\n",ans[q2[i]]);}

我的代码照题解上来说复杂度是O(q2)的但是不知道为什么爆0了,压根找不出错,明天拿来跟孔爷对拍一下好了,先放着

#include <iostream>using namespace std;const int maxn=100005;struct Node{    int l,r,k,t;}p[maxn];int A[maxn];int n,q,l,x,r,y,opt,k,T,cnt;int tot=0;inline int read(){    int f=0,x=1;char c=getchar();    while(!isdigit(c)){        if(c=='-')x=-1;        c=getchar();    }    while(isdigit(c))f=f*10+c-'0',c=getchar();    return f*x;}int main(){    n=read();    q=read();    for(int i=1;i<=n;i++)A[i]=read();    for(int i=1;i<=q;i++){        opt=read();        if(opt==1){            p[++tot].l=x=read();            p[tot].r=y=read();            p[tot].k=k=read();            p[tot].t=i;        }        else{            x=read();            y=read();            T=A[x],cnt=0;            //printf("%d ",T);            //if(T>=y)cnt+=p[j].t-p[j-1].t;            for(int j=1;j<=tot;j++){                //printf("%d ",T);                if(T>=y)cnt+=p[j].t-p[j-1].t;                if(p[j].l<=x&&p[j].r>=x)T+=p[j].k;            }            if(T>=y)cnt+=i-p[tot].t;            printf("%d\n",cnt);        }    }    return 0;}

话说题解里还有孔爷写的呢%%%%%%%

原创粉丝点击