zoukankan      html  css  js  c++  java
  • 【考试反思】联赛模拟测试17

    林sir (mathbb{AK})

    气抖冷,林sir居然站起来了

    我 = = 算了

    不开 long long 见祖宗

    T1: 30 ( ightarrow) 0

    T1:简单的区间

    简单分治 并不

    一定要养成 #define int long long 的好习惯啊 (滑稽)

    在分治时,先处理完本层跨过终点的合法区间,然后向下递归。在本层处理时,分最大值在中点左边和最大值在中点右边处理。下面以在中点左边为例:

    设左右端点的指针是 (i,j),中点左边的和为 (sumi),中点右边的和为 (sumj)。合法区间需要满足 (sumi+sumj-Maxequiv 0pmod k)。那么 (i) 一步步向左扩展,我们需要找到一个符合条件的 (sumj),我们只需要开桶维护即可,符合条件的 (sumj) 即是 (k-sumi+Max)

    然后就是中点右面,反过来即可。

    注意清空桶的时候不要 memset,否则会和暴力一个分。

    HISKrrr:这真是板子题

    Code
    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    const int maxn=1e6+10;
    int n,K,ans;
    int a[maxn];
    
    inline int read(){
        int x=0;bool fopt=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-')fopt=0;
        for(;isdigit(ch);ch=getchar())x=(x<<3)+(x<<1)+ch-48;
        return fopt?x:-x;
    }
    
    int top;
    int cnt[maxn],sta[maxn];
    void Solve(int l,int r){
        if(l==r)return;
        int mid=(l+r)>>1;
        int i=mid,j=mid+1;
        int Max=0,sumi=0,sumj=0;
        for(i=mid;i>=l;i--){
            Max=max(Max,a[i]);sumi=(sumi+a[i])%K;
            while(a[j]<=Max&&j<=r){
                sumj=(sumj+a[j])%K;
                cnt[sumj]++;sta[++top]=sumj;
                j++;
            }
            ans+=cnt[((K-sumi+Max)%K+K)%K];
        }
        while(top)cnt[sta[top--]]=0;
        i=mid,j=mid+1;
        Max=0,sumi=0,sumj=0;
        for(j=mid+1;j<=r;j++){
            Max=max(Max,a[j]);sumj=(sumj+a[j])%K;
            while(a[i]<Max&&i>=l){//注意这不能取等了,否则会重
                sumi=(sumi+a[i])%K;
                cnt[sumi]++;sta[++top]=sumi;
                i--;
            }
            ans+=cnt[((K-sumj+Max)%K+K)%K];
        }
        while(top)cnt[sta[top--]]=0;
        Solve(l,mid);
        Solve(mid+1,r);
    }
    
    signed main(){
    #ifndef LOCAL
        freopen("interval.in","r",stdin);
        freopen("interval.out","w",stdout);
    #endif
        n=read();K=read();
        for(int i=1;i<=n;i++)
            a[i]=read();
        Solve(1,n);
        printf("%lld
    ",ans);
        return 0;
    }
    

    T2:简单的玄学

    很玄学。(1leq nleq 10^{18},2leq mleq 10^{18})

    显然答案是 (1-cfrac{(2^n)^{underline m}}{2^{nm}}=1-cfrac{prodlimits_{i=2^n-m+1}^{2^n-1}i}{2^{n(m-1)}})。忽略前面的 (1) 算后面即可。但是存不下。注意到模数很小,所以可以在这上面下手。

    所以我们发现当 (m>10^6+3) 的时候,取模一定是 (0) 了,直接 break 掉就行了。

    所以还有约分这个事。发现能约的因子只有 (2)

    对于任意一个 (1leq a<2^n)(a)(2^n-a) 的中 2 的次数相同。

    所以我们要求的就是 ((m-1)!) 中因子 (2) 的个数。这个有一个 (O(log m)) 的经典做法。

    for(int i=2;i<=m;i<<=1)
        cnt+=m/i;
    

    例如 (m-1=9),那以上代码就是模拟的以下过程:

    1 × 2 × 3 × 4 × 5 × 6 × 7 × 8 × 9
        1       1       1       1     i=2
                1               1     i=4
                                1     i=8
    

    发现每个数都正好被统计了 (2) 的因数个数次。

    其实没必要真的去约分。我们求出来个数之后,(a)(b) 都乘上 (2) 的逆元的个数次方即可。

    还有要注意的就是算分母的时候不要 qpow(2,n*m) 了,否则直接爆掉 long long

    Code
    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    const int Mod=1e6+3;
    const int inv2=500002;
    int n,m;
    
    inline int qpow(int x,int b){
        int ans=1,base=x;
        while(b){
            if(b&1)ans=ans*base%Mod;
            base=base*base%Mod;
            b>>=1;
        }
        return ans;
    }
    
    signed main(){
    #ifndef LOCAL
        freopen("random.in","r",stdin);
        freopen("random.out","w",stdout);
    #endif
        scanf("%lld%lld",&n,&m);
        if((double)log2(m)-(double)n>1e-6)return !puts("1 1");
        int a=1,p=qpow(2,n),b=qpow(p,m);
        for(int i=1;i<=m;i++){
            a=a*(p-i+1)%Mod;
            if(!a)break;
        }
        int cnt=n;m--;
        for(int i=2;i<=m;i<<=1)
            cnt+=m/i;
        a=a*qpow(inv2,cnt)%Mod;
        b=b*qpow(inv2,cnt)%Mod;
        printf("%lld %lld
    ",(b-a+Mod)%Mod,b);
        return 0;
    }
    

    T3:简单的填数

    瞎贪得 10 分

    正解是贪心加模拟,比较麻烦,以后有时间补吧

    T4:聪聪和可可

    原题,但没做过。

    用 bfs 预处理两点之间最短路距离和猫走的路径,然后可以用记忆化搜索简单转移。

    Code
    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=1e3+10;
    int n,m,ccst,kkst;
    int deg[maxn];
    double ans;
    
    struct Edge{
        int from,to,nxt;
    }e[maxn<<1];
    
    inline int read(){
        int x=0;bool fopt=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-')fopt=0;
        for(;isdigit(ch);ch=getchar())x=(x<<3)+(x<<1)+ch-48;
        return fopt?x:-x;
    }
    
    int head[maxn],cnt;
    inline void add(int u,int v){
        e[++cnt].from=u;
        e[cnt].to=v;
        e[cnt].nxt=head[u];
        head[u]=cnt;
    }
    
    int dis[maxn][maxn],p[maxn][maxn];//猫在i,鼠在j,猫下一步走p[i][j]
    void bfs(int s){
        queue<int> q;
        q.push(s);
        while(!q.empty()){
            int u=q.front();q.pop();
            int temp=p[s][u];
            for(int i=head[u];i;i=e[i].nxt){
                int v=e[i].to;
                if(dis[s][v]==-1||(dis[s][u]+1==dis[s][v]&&temp<p[s][v])){
                    dis[s][v]=dis[s][u]+1;
                    p[s][v]=temp?temp:v;//p[s][s]==0 那v就是下一步
                    q.push(v);
                }
            }
        }
    }
    
    double f[maxn][maxn];
    double dfs(int cpos,int kpos){
        if(cpos==kpos)return 0;
        if(p[cpos][kpos]==kpos||p[p[cpos][kpos]][kpos]==kpos)return f[cpos][kpos]=1.0;
        if(f[cpos][kpos])return f[cpos][kpos];
        double sum=dfs(p[p[cpos][kpos]][kpos],kpos);
        for(int i=head[kpos];i;i=e[i].nxt){
            int v=e[i].to;
            sum+=dfs(p[p[cpos][kpos]][kpos],v);
        }
        return f[cpos][kpos]=1.0*sum/(deg[kpos]+1)+1;
    }
    
    int main(){
    #ifndef LOCAL
        freopen("cchkk.in","r",stdin);
        freopen("cchkk.out","w",stdout);
    #endif
        memset(dis,-1,sizeof(dis));
        n=read();m=read();ccst=read();kkst=read();
        for(int i=1;i<=m;i++){
            int u=read(),v=read();
            add(u,v);add(v,u);
            deg[u]++;deg[v]++;
        }
        for(int i=1;i<=n;i++)
            bfs(i);
        printf("%.3lf
    ",dfs(ccst,kkst));
        return 0;
    }
    
  • 相关阅读:
    【读书笔记】iOS-UDID
    【读书笔记】iOS-优化内存
    【读书笔记】iOS-处理内存警告
    【读书笔记】iOS-方法声明
    【读书笔记】iOS-属性
    【读书笔记】iOS-强类型与弱类型
    【读书笔记】iOS-Objective-C编程
    【读书笔记】iOS-Interface Builder
    【读书笔记】iOS-开发者证书
    【读书笔记】iOS-成为一名开发者
  • 原文地址:https://www.cnblogs.com/Midoria7/p/13819768.html
Copyright © 2011-2022 走看看