• qbzt周末刷题班5题解


    T1

    读入一个(n),对于一个三元组((i,j,k))满足要求当且仅当(1≤i,j,k≤n)(i×j≥k)。求符合条件的三元组的数量。
    对于30%的数据(n≤100)
    对于60%的数据(n≤5000)
    对于100%的数据(n≤100000)

    暴力:(O(n^3))暴力枚举

    60pts:
    ( ecause i imes jgeqslant k\ herefore igeqslant lceilfrac{k}{j} ceil )
    对于每个((j,k)),都有(iin [lceilfrac{k}{j} ceil,n])符合条件
    所以我们可以枚举(j,k),复杂度(O(n^2))

    100pts((O(n)做法)):
    在60pts枚举时,注意到如果(kleqslant j),则当前的((j,k))的贡献为(n)
    所以将((j,k))产生的贡献分为两部分:
    1.(kleqslant j:) 一个(k)的贡献为(n)。且对于每个(j),都有(j)个符合条件的(k),所以总贡献为(j imes n)
    2.(k>j:) 某个(k)产生的贡献为(n-lceilfrac{k}{j} ceil+1)
    且当(lceilfrac{k}{j} ceil=2)时,(kin [j+1,2j];)(lceilfrac{k}{j} ceil=3)时,(kin [2j+1,3j]........)
    最后一段:当(lceilfrac{k}{j} ceil=x+1)时,(kin[xj+1,n])((x=lfloorfrac{n}{j} floor))
    发现非最后一段的区间长为(j),那么非最后一段的所有贡献可以加和,即(j imes sum_{l=2}^x{n-l+1}),发现是一个等差数列
    最后一段的贡献:(((n-x) imes (n-xj))
    整理一下:
    (ans=sum_{i=1}^n i imes (n+frac{(2n-x)(x-1)}{2})+(n-xi)(n-x),x=lfloorfrac{n}{i} floor)
    可以(O(n))求出答案
    PS:十年OI一场空,不开longlong见祖宗
    (Code)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<cstring>
    #include<cstdlib>
    #include<set>
    #define pa pair<int,int>
    #define pi pair<ull,ll>
    using namespace std;
    const int inf=2147483640;
    typedef long long ll;
    typedef unsigned long long ull;
    inline ll read(){
    	char ch=getchar();
    	ll x=0;bool f=0;
    	while(ch<'0'||ch>'9'){
    		if(ch=='-') f=1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9'){
    		x=(x<<3)+(x<<1)+(ch^48);
    		ch=getchar();
    	}
    	return f?-x:x;
    }
    int n;
    ull ans;
    int main(){
    	n=read();
    	for(int i=1;i<=n;i++){
    		ans+=(ull)n*i;
    		ull x=n/i; 
    		ans+=(ull)i*((ull)(2*n-x)*(ull)(x-1)/2);
    		ans+=(ull)(n-x*i)*(ull)(n-x);
    	}
    	printf("%llu
    ",ans);
    }
    

    T2

    一些废话:连暴力都不会了.orz

    先从暴力看起。我们可以枚举每一个关键点作为出发点。(f[i][j][o])表示从点(i)到点(j)是否有长度(mod p=o)的路径。这样有40pts。

    优化一下:如果走某条边奇数次,和走这条边一次所到达的点是一样的。走这条边偶数次,和不走所到达的边是一样的。而题目保证(p)是奇数。所以我们可以考虑走某条边(p)(2p)次来调节这条边的贡献。

    上面的暴力需要枚举所有关键点作为出发点,这很不优秀,我们想把它优化掉。那么我们能不能减少枚举的点的个数?

    我们考虑某一点(o)和合法路径的关系。如果图中存在一条从(x)(y)的合法路径,且路径上的某一点(z)可以到达(o)。那么我们可以通过走(2p)((o,z))来抵消这条边在模意义下的贡献。这样就可以使这条合法路径经过点(o)。而整个图是无向图,所有点都是联通的,所以点(o)可以是任意一点。这样就可以优化掉枚举起点。

    优化两下:我们发现不只是边((o,z))可以被调节,图上所有的边都可以被调节。那最后的路径长度只和每条边被经过的次数有关,和经过的点没什么关系。
    设某条边的边长为(A),那么((k_1 imes A) mod p)可以表示所有的((k_2 imes gcd(A,p)) mod p)

    证明(以下简称(gcd(A,p))(gcd)):

    [x 设A=mp+a,a=ycdot gcd\ herefore left{egin{aligned}Aequiv ycdot gcd (mod p)\ frac{A}{gcd}equiv mfrac{p}{gcd}+y (mod p)\ end{aligned} ight.\​ 现在我们要用k_1cdot ycdot gcd (mod p)来表示k_2cdot (mfrac{p}{gcd}+y) (mod p)\ k_2cdot (mfrac{p}{gcd}+y)equiv k_2cdot mcdot pcdot gcd^{-1}+k_2cdot y (mod p)\ 即k_2cdot (mfrac{p}{gcd}+y)equiv k_2cdot y (mod p)\ 所以我们现在要用k_1cdot ycdot gcd (mod p)来表示k_2cdot y (mod p)\即用k_1cdot gcd (mod p)来表示k_2 (mod p)\ 若k_1cdot gcdequiv k_2 (mod p)\则k_1equiv k_2cdot gcd^{-1} (mod p)\对于任意的k_2,k_1都有解,证毕 ]

    所以若存在一条路径长(A)使得(gcd(A,p) | gcd(L,p)),则存在一个(k_1cdot Aequiv k_2cdot L (mod p)),即路径合法。(k_1,k_2)的问题可以通过多次走(A)来解决。
    所以我们只需要求出所有边权的(gcd),看是否能整除(gcd(L,p))即可

    T3

    暴力:枚举(b),看起来有30pts,其实它有50pts

    正解:
    我们知道(a^b equiv a^{b mod p} mod p,a^a equiv a^a mod p),所以不妨让(b)(a)同余,设(b=kp+a)
    根据扩展欧拉定理,当(p)(a)互质时,(a^b equiv a^{b mod phi(p)} mod p)(扩展欧拉定理见这里((stO)一扶苏一(Orz))),设(b=k_2codt phi(p)+a)
    可得(b=pcdot phi(p)+a)
    (p)(a)不互质时:因为(ageqslant 64),所以等价于互质的情况

    T4


    题目背景过酸已隐藏

    暴力:(O(n^3))暴力枚举

    优化:
    合法的情况:

    对于一个(i)来说,最优的(j)(i+d_i),且(k)要满足(kleqslant 2j-i)。因为当(j)(i,k)中点时,(k=2j-i),但(j)更靠近(k)

    对于每个(i),可以确定一个最优的(j),进而确定最远可能覆盖到的(k=2j-i)。发现对于这时的(i,j),符合条件的(k)的范围为([i+2,2j-i])。(就算(j>k)也木有关系(虽然题目要求(j)(i,k)中间)(我也不造为啥))
    这样我们把(i)(f_k)产生的贡献放到以(j)为下标的数组里,维护后缀和。
    std:

    #include<bits/stdc++.h>
    #define N 3200000
    #define lowbit(x) ((x)&-(x))
    using namespace std;
    int n,d[N],f[N];
    int ans;
    vector<int>a[N];
    int t[N]; 
    namespace bit{
    	int t[N];
    	int insert(int x,int a){
    		x=n-x+1;
    		for(int i=x;i<=n;i+=lowbit(i))t[i]+=a;
    		return 0;
    	}
    	int query(int x){
    		x=n-x+1;
    		int ans=0;
    		for(int i=x;i;i-=lowbit(i))ans+=t[i];
    		return ans;
    	}
    }
    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*10+ch-'0';
            ch=getchar();
        }
        return x*f;
    };
    int main(){
    	freopen("beacon.in","r",stdin);
    	freopen("beacon.out","w",stdout);
    	n=read();
    	for(int i=1;i<=n;i++)d[i]=read();
    	for(int k=3;k<=n;k++){
    		int i=k-2;
    		int j=i+d[i];
    		int l=2*j-i+1;
    		l=min(l,n+1);
    		a[l].push_back(j);
    		bit::insert(min(j,n),1);
    		for(int o=0;o<a[k].size();o++){
    			bit::insert(min(a[k][o],n),-1);
    		}
    		f[k]=bit::query(max(k-d[k],1));
    	}
    //	for(int i=1;i<=n;i++)printf("%d ",f[i]);
    //	printf("
    ");
    //	return 0;
    	for(int i=1;i<=n;i++)ans^=f[i];
    	printf("%d
    ",ans);
    }
    
  • 相关阅读:
    浅谈线段树
    浅谈KMP
    20200729线上模拟题解
    20200727线上模拟题解
    声明
    tarjan--割点,缩点
    20201029模拟
    高精模板
    二分图--二分图的几种模型
    树的直径与树的重心
  • 原文地址:https://www.cnblogs.com/lcez56jsy/p/13910205.html
Copyright © 2020-2023  润新知