今天山大附中的同学们跟我们一起来考试,他们好强啊,再次认识到了自己与其他人的差距;

本来可以和土哥一样是rk3的,不过不知道什么的原因,我的t2代码交c++就是50,交c++(NOI)就是100,直接rk3掉rk5了

T1简单的区间

这个题我第一眼看有点像之前写过的一道叫入镇曲的题目,也像noip模拟11的t3,都是维护一个区间的最值,

于是我写了个单调栈维护了一下区间的左端点和右端点,然后写了一个类似于入镇曲的O(n^n)的做法,拿了个50分;

其实这道题正解是写一颗主席树,然后可以O(nlog(n))写过,思路就和noip模拟11的t3一样,不过,我不会写主席树,还没学;

从fengwu那位STL之神那里学来了一手vector做法

其实思路大体没有啥变化,我们利用二分查找可以查出一个区间合法的个数,最后复杂度依然是Onlogn的,常数也比用主席树要小

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 #define lid id<<1
 4 #define rid id<<1|1
 5 using namespace std;
 6 inline int read()
 7 {
 8     int x=0,f=1;
 9     char ch=getchar();
10     while(ch<'0'||ch>'9')
11     {
12         if(ch=='-') f=-1;
13         ch=getchar();
14     }
15     while(ch>='0'&&ch<='9')
16     {
17         x=(x<<1)+(x<<3)+(ch^48);
18         ch=getchar();
19     }
20     return x*f;
21 }
22 inline int max(int x,int y){if(x<y)return y;return x;}
23 inline int min(int x,int y){if(x<y)return x;return y;}
24 const int maxn=4e5+1;
25 int a[maxn],n,k;
26 int pre[maxn];
27 int le[maxn],re[maxn];
28 stack<int >s;
29 int mod[1000001];
30 signed main()
31 {
32     n=read(),k=read();
33     for(int i=1;i<=n;i++)
34     {
35         a[i]=read();
36         pre[i]=(a[i]+pre[i-1])%k;
37     }
38     for(int i=1;i<=n;i++)
39     {
40         while(!s.empty()&&a[i]>a[s.top()])
41         s.pop();
42         le[i]=s.empty()?1:s.top()+1;
43         s.push(i);
44     }
45     while(!s.empty())
46     s.pop();
47     for(int i=n;i;i--)
48     {
49         while(!s.empty()&&a[i]>=a[s.top()])
50         s.pop();
51         re[i]=s.empty()?n:s.top()-1;
52         s.push(i);
53     }
54     int ans=0,jb=0;
55     for(int i=1;i<=n;i++)
56     {
57         int l=le[i],r=re[i];
58         int maxx=a[i]%k;
59         for(int j=l;j<i;j++)
60         mod[pre[j-1]]++;
61         ans+=mod[(pre[i]-maxx+k)%k];
62         mod[pre[i-1]]++;
63         for(int j=i+1;j<=r;j++)
64         ans+=mod[(pre[j]-maxx+k)%k];
65         for(int j=l;j<=i;j++)
66         mod[pre[j-1]]=0;
67     }
68     cout<<ans;
69 }
50
 1 #include<bits/stdc++.h>
 2 #define int long long
 3 #define lid id<<1
 4 #define rid id<<1|1
 5 using namespace std;
 6 inline int read()
 7 {
 8     int x=0,f=1;
 9     char ch=getchar();
10     while(ch<'0'||ch>'9')
11     {
12         if(ch=='-') f=-1;
13         ch=getchar();
14     }
15     while(ch>='0'&&ch<='9')
16     {
17         x=(x<<1)+(x<<3)+(ch^48);
18         ch=getchar();
19     }
20     return x*f;
21 }
22 inline int max(int x,int y){if(x<y)return y;return x;}
23 inline int min(int x,int y){if(x<y)return x;return y;}
24 const int maxn=1e6+1;
25 int a[maxn],n,k;
26 int pre[maxn],ans=0;
27 int le[maxn],re[maxn];
28 stack<int >s;
29 int mod[1000001];
30 vector<int > q[1000001];
31 void cz(int i,int l,int r)
32 {
33     if(i-l<r-i)
34     {
35         for(int j=l;j<=i;j++)
36         {
37             int tmp=(pre[j-1]+a[i])%k;
38             int ans1=lower_bound(q[tmp].begin(),q[tmp].end(),i)-q[tmp].begin();
39             int ans2=upper_bound(q[tmp].begin(),q[tmp].end(),r)-q[tmp].begin();
40             ans+=ans2-ans1;
41         }    
42     }
43     else
44     {
45         for(int j=i;j<=r;j++)
46         {
47             int tmp=(pre[j]-(a[i]%k)+k)%k;
48             int ans1=lower_bound(q[tmp].begin(),q[tmp].end(),l-1)-q[tmp].begin();
49             int ans2=upper_bound(q[tmp].begin(),q[tmp].end(),i-1)-q[tmp].begin();
50             ans+=ans2-ans1;
51         }
52     }
53 }
54 signed main()
55 {
56     n=read(),k=read();
57     q[0].push_back(0);
58     for(int i=1;i<=n;i++)
59     {
60         a[i]=read();
61         pre[i]=(a[i]+pre[i-1])%k;
62         q[pre[i]].push_back(i);
63     }
64     for(int i=1;i<=n;i++)
65     {
66         while(!s.empty()&&a[i]>a[s.top()])
67         s.pop();
68         le[i]=s.empty()?1:s.top()+1;
69         s.push(i);
70     }
71     while(!s.empty()) s.pop();
72     for(int i=n;i>=1;i--)
73     {
74         while(!s.empty()&&a[i]>=a[s.top()])
75         s.pop();
76         re[i]=s.empty()?n:s.top()-1;
77         s.push(i);
78     }
79     for(int i=1;i<=n;i++)
80     cz(i,le[i],re[i]);
81     cout<<ans-n;
82 }
AC

T2简单的玄学

看题目,怎么办,好象是概率题,再仔细一点,原来就是个数学题,推了大概半个小时,直接就推出来了,其实只要掌握好了数论,

这种题目确实不是很难(只不过让评测机吃掉了50分);

下面直接说一下正解,题目上说让我们求出至少有两个数是相等的概率,那我们可以求出1减去一个都不相等的概率,得出的结果肯定是一样的

首先,全部的情况肯定是2^nm,那么分母就定了,完全不相等的情况就是从(2^n)连乘到(( 2^n )-m+1),题目中告诉我们说

分子和分母都要化成最简的,那么我们要约分啊

由于分母是2的次幂,所以它的质因子只有2,那我们就要找上面那个数字中2的个数,那么我们应该怎么来找呢??

首先我们应该清楚一条性质2^k-x里2的因子数=x里面2的因子数。证明:设x=x/(2^y)*(2^y),2^k=(2^(k-y)*2^y),那么很显然2^(k-y)-x不是偶数

那么剩下就没啥了,挺基础的一些操作

#include<bits/stdc++.h>
#define ll long long
#define int long long
using namespace std;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
const int mod=1e6+3;
const int phi=1e6+2;
inline int ksm(int j,int k,int l)
{
    int f=1;
    j=j%l;
    while(k>0)
    {
        if(k%2==1)
        {
            f=(f*j)%l;
        }
        k*=0.5;
        j=(j*j)%l;
    }
    return f;
}
inline int gcd(int a,int b)
{
    if(!b)
    return a;
    return gcd(b,a%b);
}
int n,m;
signed main()
{
    n=read(),m=read();        
    if(n==1)
    {
        cout<<1<<" "<<1;
        return 0;
    }
    int maxx=ksm(2,n%phi,mod);
    int y=ksm(maxx,m%phi,mod);
    int x=1;
    int sum=n;
    for(int i=0;i<=m-1;i++)
    {
        x=(x*(maxx-i))%mod;
        if(!x)
        break;
    }//2×500002%mod=1 所以2的逆元就是500002
    for(int i=1;((ll)1<<i)<=m-1;i++)
    {
        sum+=(m-1)/((ll)1<<i);
    }
    y=(y*ksm(500002,sum,mod))%mod;
    x=(x*ksm(500002,sum,mod))%mod;
    cout<<(y-x+mod)%mod<<" "<<y;
}
T2

T3简单的填数

其实挺难的,不,是真的十分难,唉,果然还是我太弱了

题解简直不说人话,就是模拟,然后分情况讨论

up代表上界,down代表下界;

先不要考虑已经填了的,up2位一进,down5位一进

然后再考录已经填了的,a[ i ]>上界就是不合法状态

如果a[ i ]==up,那么取min(2,up);

否则让up=a[ i ],次数变成2;

下界类似,就不再写了

#include<bits/stdc++.h>
using namespace std;
const int maxn=1010101;
struct node {
    int cnt,x;
}up[maxn],down[maxn];
int a[maxn],vis[maxn],n;
inline int min(int x,int y){return x<y?x:y;}
inline int max(int x,int y){return x>y?x:y;}
inline void swap(int &x,int &y){x^=y^=x^=y;}
inline int abs(int x){return x<0?-x:x;}
inline int gcd(int x,int y){return y?x:gcd(y,x%y);}
inline int lcm(int x,int y){return x/gcd(x,y)*y;}
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')    
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    a[i]=read();
    if(a[1]!=1&&a[1]!=0)
    {
        puts("-1");
        return 0;
    }
    up[1].cnt=1,up[1].x=1;
    down[1].cnt=1,down[1].x=1;
    for(int i=2;i<=n;i++)
    {
        up[i]=up[i-1];
        down[i]=down[i-1];
        if(++up[i].cnt>2)
        up[i].cnt=1,up[i].x++;
        if(++down[i].cnt>5)
        down[i].cnt=1,down[i].x++;
        if(a[i])
        {
            if(up[i].x>a[i])
            up[i].x=a[i],up[i].cnt=2;
            if(down[i].x<a[i])
            down[i].x=a[i],down[i].cnt=1;    
            if(up[i].x<a[i]||down[i].x>a[i])
            {
                cout<<-1;
                return 0;    
            }        
        }
    }
    if(up[n].cnt==1)
    up[n].x=up[n-1].x;
    if(up[n].x<down[n].x)
    {
        puts("-1");
        return 0;
    }
    printf("%d\n",up[n].x);
    vis[up[n].x]=1;
    a[n]=up[n].x;
    for(int i=n-1;i>=1;i--)
    {
        if(!a[i])
        {
            int t=min(a[i+1],up[i].x);
            if(vis[t]==5)
            --t;
            a[i]=t;
        }
        vis[a[i]]++;
    }
    for(int i=1;i<=n;i++)
    printf("%d ",a[i]);
}
T3

 

posted on 2021-07-12 19:00  JYFHYX  阅读(38)  评论(0编辑  收藏  举报