zoukankan      html  css  js  c++  java
  • 21杭电多校第一场

    A

    签到题,显然可以取到所有(<lceilfrac{n}{2} ceil)的所有数,则答案就是(n-1)的最高位(2^x-1)

    #include<bits/stdc++.h>
    #define inf 2139062143
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    #define MAXN 100100
    #define MOD 998244353
    #define Fill(a,x) memset(a,x,sizeof(a))
    #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
    #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
    #define ren for(int i=fst[x];i;i=nxt[i])
    #define pls(a,b) (a+b)%MOD
    #define mns(a,b) (a-b+MOD)%MOD
    #define mul(a,b) (1LL*(a)*(b))%MOD
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    ll n,T;
    int main()
    {
    	rep(T,1,read())
    	{
    		n=read();
    		ll p=1;while(p<n) p*=2;
    		p/=2;printf("%lld
    ",max(p-1,0LL));
    	}
    }
    

    B

    (kd-tree)暴力查询,记录一下子树内的权值和,每次修改的时候由下至上更新

    #include<bits/stdc++.h>
    #define inf 2139062143
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    #define MAXN 200100
    #define MOD 998244353
    #define Fill(a,x) memset(a,x,sizeof(a))
    #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
    #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
    #define ren for(int i=fst[x];i;i=nxt[i])
    #define pls(a,b) (a+b)%MOD
    #define mns(a,b) (a-(b)+MOD)%MOD
    #define mul(a,b) (1LL*(a)*(b))%MOD
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,xx[MAXN],yy[MAXN],w[MAXN],id[MAXN],rr[MAXN],Dim;
    inline ll sqr(ll x){return x*x;}
    struct node {int mx[2],mn[2],d[2],l,r,id;ll sum,w;};
    bool operator < (const node a,const node b) {return a.d[Dim]<b.d[Dim];}
    struct kd_tree
    {
        int Rt,fa[MAXN];node tr[MAXN],l,r;
        void upd(int k)
        {
        	l=tr[tr[k].l],r=tr[tr[k].r];
    		rep(i,0,1)
            {
                if(tr[k].l)
    				tr[k].mx[i]=max(tr[k].mx[i],l.mx[i]),tr[k].mn[i]=min(tr[k].mn[i],l.mn[i]);
                if(tr[k].r)
    				tr[k].mx[i]=max(tr[k].mx[i],r.mx[i]),tr[k].mn[i]=min(tr[k].mn[i],r.mn[i]);
            }
        }
        int build(int l,int r,int now)
        {
            int mid=l+r>>1;Dim=now;nth_element(tr+l,tr+mid,tr+r+1);
            rep(i,0,1) tr[mid].mn[i]=tr[mid].mx[i]=tr[mid].d[i];
            id[tr[mid].id]=mid;
            if(l<mid) tr[mid].l=build(l,mid-1,now^1),fa[tr[mid].l]=mid;
            if(mid<r) tr[mid].r=build(mid+1,r,now^1),fa[tr[mid].r]=mid;
    		upd(mid);return mid;
        }
        void mdf(int k,int w)
        {
    		tr[k].w=w;tr[k].sum+=w;
    		for(k=fa[k];k;k=fa[k]) tr[k].sum+=w;
    	}
        void init()
    	{
    		rep(i,1,n)
    		{
    			tr[i].id=i,tr[i].l=tr[i].r=fa[i]=tr[i].sum=tr[i].w=0;
    			xx[i]=tr[i].d[0]=read(),yy[i]=tr[i].d[1]=read();
    			w[i]=read(),rr[i]=read();
    		}
    		Rt=build(1,n,0);
    	}
    	inline int ok(int cx,int cy,int R,int a,int b)
    	{
    		return sqr(a-cx)+sqr(b-cy)<=sqr(R);
    	}
    	inline int in(int cx,int cy,int R,int x1,int y1,int x2,int y2)
    	{
    		if(!ok(cx,cy,R,x1,y1)) return 0;
    		if(!ok(cx,cy,R,x1,y2)) return 0;
    		if(!ok(cx,cy,R,x2,y1)) return 0;
    		if(!ok(cx,cy,R,x2,y2)) return 0;
    		return 1;
    	}
    	inline int out(int cx,int cy,int R,int x1,int y1,int x2,int y2)
    	{
            int a,b;
    		if(x1<=cx&&cx<=x2) a=cx;
            else if(cx<x1) a=x1;else a=x2;
    		if(y1<=cy&&cy<=y2) b=cy;
            else if(cy<y1) b=y1;else b=y2;
    		if(ok(cx,cy,R,a,b)) return 0;
    		else return 1;
    	}
    	ll query(int k,int x,int y,int R,ll res=0)
    	{
    		if(!tr[k].sum) return 0;
    		if(in(x,y,R,tr[k].mn[0],tr[k].mn[1],tr[k].mx[0],tr[k].mx[1]))
    			return tr[k].sum;
    		if(out(x,y,R,tr[k].mn[0],tr[k].mn[1],tr[k].mx[0],tr[k].mx[1]))
    			return 0;
    		if(ok(x,y,R,tr[k].d[0],tr[k].d[1])) res=tr[k].w;
    		if(tr[k].l) res+=query(tr[k].l,x,y,R);
    		if(tr[k].r) res+=query(tr[k].r,x,y,R);
    		return res;
    	}
        void solve()
        {
        	rep(i,1,n)
    		{
    			printf("%lld
    ",query(Rt,xx[i],yy[i],rr[i])+w[i]);
    			mdf(id[i],w[i]);
    		}
    	}
    }kd;
    int main()
    {
    	rep(T,1,read())
    		{n=read();kd.init();kd.solve();}
    }
    

    C

    将每个边是否选表示为一个(0/1)变量,用异或方程表示限制,则答案为(2^k)其中(k)为自由元个数

    则题目中所有环没有公共边只有公共点,可以表示为和一个节点相邻的边数为偶数

    每个方块周围边数的奇偶性也同样可以表示

    可以用(bitset)加速这个异或方程的高斯消元求解过程

    #include<bits/stdc++.h>
    #define inf 2139062143
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    #define MAXN 100100
    #define MOD 998244353
    #define Fill(a,x) memset(a,x,sizeof(a))
    #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
    #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
    #define ren for(int i=fst[x];i;i=nxt[i])
    #define pls(a,b) (a+b)%MOD
    #define mns(a,b) (a-b+MOD)%MOD
    #define mul(a,b) (1LL*(a)*(b))%MOD
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,m,tot,idx[20][20],idy[20][20],cnt,ans;
    char s[20];
    bitset<700> a[700];
    int main()
    {
    	int now,pos;rep(T,1,read())
    	{
    		n=read()-1,m=read()-1;tot=cnt=0;ans=-1;
    		rep(i,1,n+1) rep(j,1,m) idx[i][j]=++tot;
    		rep(i,1,n) rep(j,1,m+1) idy[i][j]=++tot;
    		rep(i,1,n+1) rep(j,1,m+1)
    		{
    			a[++cnt].reset();
    			if(i>1) a[cnt][idy[i-1][j]]=1;
    			if(j>1) a[cnt][idx[i][j-1]]=1;
    			if(i<=n) a[cnt][idy[i][j]]=1;
    			if(j<=m) a[cnt][idx[i][j]]=1;
    		}
    		rep(i,1,n)
    		{
    			scanf("%s",s+1);
    			rep(j,1,m) if(s[j]!='.')
    			{
    				a[++cnt].reset();a[cnt][tot+1]=s[j]-'0';
    				a[cnt][idx[i][j]]=a[cnt][idy[i][j]]=1;
    				a[cnt][idx[i+1][j]]=a[cnt][idy[i][j+1]]=1;
    			}
    		}
    		n=tot,m=cnt;now=1,pos;
    		rep(i,1,n)
    		{
    			pos=0;rep(j,now,m) if(a[j][i]) {pos=j;break;}
    			if(!pos) continue;
    			if(pos!=now) swap(a[pos],a[now]);
    			rep(j,now+1,m) if(a[j][i]) a[j]^=a[now];
    			now++;
    		}
    		rep(i,now,m) if(a[i].any()) {ans=0;break;}
    		if(~ans) {puts("0");continue;}
    		ans=1;rep(i,now,n) ans=mul(ans,2);
    		printf("%d
    ",ans);
    	}
    }
    

    D

    (f(i,j))表示前(j)个物品总价值为(i)的方案数,则有

    [f(i,j)=f(i,j-1)+f(i-a_j,j)=sumlimits_{t=0}^{lfloor frac{i}{a_j} floor}f(i-tcdot a_j,j-1) ]

    最好将上面的向下取整扔掉,考虑将(i)写成(kcdot LCM+r)的形式,其中(r=k'a_j+q)

    [f(kcdot LCM+r,j)=sumlimits_{t=0}^{kcdot LCM/a_j+k'}f(kcdot LCM+r-tcdot a_j,j-1) ]

    可以证明(f(kcdot LCM+r,j))为关于(k)(j-1)次多项式,记为(F_{j,r})(f(kcdot LCM+r,j)=F_{j,r}(k))

    因此可以暴力(dp)出前(ncdot LCM)项的(f(i,n))值,复杂度(O(n^2LCM))

    取出余数相同的(f)作为(F_{n,r})(n)个函数点值,使用拉格朗日插值即可求出(F_{n,r}(k))


    拉格朗日插值的构造非常暴力,设(F(x)=sumlimits_{i=1}^nf_i(x)),其中(f_i(x))表示只满足((x_i,y_i)),其余(y|_{x=x_j}=0)的函数

    (f_i(x)=y_ifrac{prod_{i eq j}x-x_j}{prod_{i eq j}x_i-x_j})即符合条件

    #include<bits/stdc++.h>
    #define inf 2139062143
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    #define MAXN 300100
    #define MOD 1000000007
    #define Fill(a,x) memset(a,x,sizeof(a))
    #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
    #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
    #define ren for(int i=fst[x];i;i=nxt[i])
    #define pls(a,b) (a+b)%MOD
    #define mns(a,b) (a-(b)+MOD)%MOD
    #define mul(a,b) (1LL*(a)*(b))%MOD
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,a[120],lcm,inv[120],f[MAXN],y[120];ll k;
    int gcd(int a,int b){return !b?a:gcd(b,a%b);}
    int Lagrange(ll x,int res=0)
    {
    	int tmp;x%=MOD;rep(i,1,n)
    	{
    		tmp=1;
    		rep(j,1,i-1) tmp=mul(tmp,inv[i-j]);
    		rep(j,i+1,n) tmp=mul(tmp,-inv[j-i]);
    		rep(j,1,n) if(i!=j) tmp=mul(tmp,x-j);
    		tmp=mul(tmp,y[i]);
    		res=pls(res,tmp);
    	}
    	return (res+MOD)%MOD;
    }
    int main()
    {
    	inv[0]=inv[1]=1;rep(i,2,105) inv[i]=mul(inv[MOD%i],(MOD-MOD/i));
    	int x,g;rep(T,1,read())
    	{
    		n=read(),k=read();lcm=1;
    		rep(i,1,n) a[i]=read(),g=gcd(lcm,a[i]),lcm=lcm/g*a[i];
    		f[0]=1;rep(i,1,n*lcm) f[i]=0;
    		rep(i,1,n) rep(j,a[i],n*lcm) f[j]=pls(f[j],f[j-a[i]]);
    		if(k<=n*lcm) {printf("%d
    ",f[k]);continue;}
    		rep(i,0,n-1) y[i+1]=f[k%lcm+i*lcm];
    		printf("%d
    ",Lagrange(k/lcm+1));
    	}
    }
    

    E

    签到题,每个合数(i)可以向他们的约数连边,贡献为(i);每个素数(p)可以和(2)连边,贡献为(2p)

    #include<bits/stdc++.h>
    #define inf 2139062143
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    #define MAXN 10010010
    #define MOD 998244353
    #define Fill(a,x) memset(a,x,sizeof(a))
    #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
    #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
    #define ren for(int i=fst[x];i;i=nxt[i])
    #define pls(a,b) (a+b)%MOD
    #define mns(a,b) (a-b+MOD)%MOD
    #define mul(a,b) (1LL*(a)*(b))%MOD
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,p[MAXN/7],tot,ntp[MAXN];ll ans[MAXN];
    void mem(int n=1e7)
    {
    	rep(i,2,n)
    	{
    		if(!ntp[i]) p[++tot]=i;
    		rep(j,1,tot) if(i*p[j]>n) break;
    			else {ntp[i*p[j]]=1;if(i%p[j]==0) break;}
    	}
    	rep(i,3,n) ans[i]=ans[i-1]+(ntp[i]?i:2*i);
    }
    int main()
    {
    	mem();
    	rep(T,1,read()) printf("%lld
    ",ans[read()]);
    }
    

    F

    转化为前缀和后,问题变为查找最近的两个数使得他们的异或和(ge k)

    从左到右加入每个前缀和,对(trie)树上的每个节点记录经过这个点的最大编号

    对每个右端点(r),在查询的时候按照(k otimes sum_r)(trie)树上遍历

    若该位为(0)(1)的子树内所有数都符合条件,选出最大值;其余情况就一直沿着(trie)树走到底再查询

    每次查询后更新答案

    #include<bits/stdc++.h>
    #define inf 2139062143
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    #define MAXN 100100
    #define MOD 998244353
    #define Fill(a,x) memset(a,x,sizeof(a))
    #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
    #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
    #define ren for(int i=fst[x];i;i=nxt[i])
    #define pls(a,b) (a+b)%MOD
    #define mns(a,b) (a-b+MOD)%MOD
    #define mul(a,b) (1LL*(a)*(b))%MOD
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,k,tr[MAXN*30][2],tot,g[30],mx[MAXN*30],ansl,ansr,ans=inf;
    void ins(int x,int id)
    {
    	int t,res=-1,p=0;dwn(i,29,0)
    	{
    		t=(x>>i)&1;
    		if(!g[i])
    		{
    			if(tr[p][t^1]) {res=max(res,mx[tr[p][1^t]]);break;}
    			if(tr[p][t]) p=tr[p][t],res=mx[p];
    		}
    		else 
    		{
    			if(tr[p][t^1]) p=tr[p][t^1],res=mx[p];
    			else {res=-1;break;}
    		}
    	}
    	//cout<<id<<" "<<res<<endl;
    	if(~res) if(id-res<ans) ans=id-res,ansl=res+1,ansr=id;
    	p=0;dwn(i,29,0)
    	{
    		t=(x>>i)&1;if(!tr[p][t]) tr[p][t]=++tot;
    		p=tr[p][t],mx[p]=id;
    	}
    }
    int main()
    {
    	rep(T,1,read())
    	{
    		n=read(),k=read();int s=0;tot=0;ans=inf;
    		dwn(i,29,0) if(k&(1<<i)) g[i]=1;else g[i]=0;
    		ins(s,0);rep(i,1,n) {s^=read();ins(s,i);}
    		if(ans!=inf) printf("%d %d
    ",ansl,ansr);
    		else puts("-1");
    		dwn(i,tot,0) tr[i][0]=tr[i][1]=0;
    	}
    }
    

    G

    (f_i)表示一共(n)个人的时候第(i)轮传回自己的方案数

    由于传(i)次球的总方案数为((n-1)^i),其中(f_i)种对应此时球在自己手中的情况,而剩余的((n-1)^i-f_i)种由于再传一次可以传回自己,则这些方案和(f_{i+1})形成了一一对应,即(f_i+f_{i+1}=(n-1)^i)

    由于(f_1=0),可以看出(f_i=(n-1)^{i-1}-(n-1)^{i-2}+cdots +(-1)^{i-2}(n-1))

    给出(f_iequiv t (mod P)),即:

    [egin{aligned} t&equiv (-1)^{i-2}(n-1)sumlimits_{i=0}^{i-2}[-(n-1)]^i (mod P)\ t&equiv (-1)^{i-2}(n-1)frac{1-[-(n-1)]^{i-1}}{1-[-(n-1)]} (mod P)\ frac{nt}{n-1}&equiv (-1)^{i-2}{1-[-(n-1)]^{i-1} } (mod P) end{aligned} ]

    需要对(i)进行奇偶性讨论分别计算

    • (i)为奇数时,(frac{nt}{n-1}equiv -[1-(n-1)^{i-1}] (mod P))(lgroupfrac{nt}{n-1}+1 group(n-1)equiv (n-1)^i (mod P))

    • (i)为奇数时,(frac{nt}{n-1}equiv 1-[-(n-1)^{i-1}] (mod P))(lgroupfrac{nt}{n-1}-1 group(n-1)equiv (n-1)^i (mod P))

    均转化为了(bsgs)的形式,套板子之后求解即可

    #include<bits/stdc++.h>
    #define inf 2139062143
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    #define MAXN 100100
    #define MOD 998244353
    #define Fill(a,x) memset(a,x,sizeof(a))
    #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
    #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
    #define ren for(int i=fst[x];i;i=nxt[i])
    #define pls(a,b) (a+b)%MOD
    #define mns(a,b) (a-(b)+MOD)%MOD
    #define mul(a,b) (1LL*(a)*(b))%MOD
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    struct HashTable
    {
    	const int mod=100007;
        int fst[MAXN],key2[MAXN],nxt[MAXN],tot;
        ll key1[MAXN];
        inline void mem(){memset(fst,0,sizeof(fst));tot=0;}
        void ins(ll k1,int k2)
        {
    		int hsh=(int)k1%mod;
            key1[++tot]=k1,key2[tot]=k2;
            nxt[tot]=fst[hsh],fst[hsh]=tot;
        }
        int find(ll k1)
        {
            int hsh=(int)k1%mod;
            for(int i=fst[hsh];i;i=nxt[i])
                if(key1[i]==k1) return key2[i];
            return -1;
        }
    }hsh;
    int qp(int x,int t,int res=1)
    {
    	for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);
    	return res;
    }
    #define inv(x) qp(x,MOD-2)
    int bsgs(int y,int z)
    {
        int ok=0;hsh.mem();
        if(!(y%MOD)) {return -1;}
        ll m=ceil(sqrt(MOD)),a=1ll,res;
        for(int i=0;i<=m;i++)
            hsh.ins(a*z%MOD,i),(a*=y)%=MOD;
        a=1ll,res=qp(y,m);
        for(int i=1,t;i<=m;i++)
        {
            (a*=res)%=MOD,t=hsh.find(a);
            if(t!=-1) return ((m*i-t)%MOD+MOD)%MOD;
        }
        return -1;
    }
    int n,x,ans1,ans2,ans;
    int main()
    {
    	int t;rep(T,1,read())
    	{
    		n=read(),x=read();
    		x=mul(x,mul(n,inv(n-1)));
    		t=mul(pls(x,1),n-1);ans1=bsgs(n-1,t);//odd
    		t=mul(mns(x,1),n-1);ans2=bsgs(n-1,t);//even
    		if(ans1!=-1&&ans1%2==0) ans1=-1;
    		if(ans2!=-1&&(ans2&1)) ans2=-1;
    		ans=min(ans1,ans2);
    		if(ans==-1) ans=max(ans1,ans2);
    		printf("%d
    ",ans);
    	}
    }
    

    H

    预处理每个点向下最远不降到哪

    枚举矩形横着的边,可以用单调栈处理出这一行每个点左右第一个下降距离比它小的点

    则这个点的答案即为((r-l-1)*dis_i),每个点都更新答案即可

    #include<bits/stdc++.h>
    #define inf 2139062143
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    #define MAXN 2020
    #define MOD 998244353
    #define Fill(a,x) memset(a,x,sizeof(a))
    #define rep(i,s,t) for(register int i=(s),i##end=(t);i<=i##end;++i)
    #define dwn(i,s,t) for(register int i=(s),i##end=(t);i>=i##end;--i)
    #define ren for(int i=fst[x];i;i=nxt[i])
    #define pls(a,b) (a+b)%MOD
    #define mns(a,b) (a-b+MOD)%MOD
    #define mul(a,b) (1LL*(a)*(b))%MOD
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,m,g[MAXN][MAXN],mx[MAXN][MAXN],ans,l[MAXN],r[MAXN],s[MAXN],tp;
    int main()
    {
    	rep(T,1,read())
    	{
    		n=read(),m=read();ans=0;
    		rep(i,1,n) rep(j,1,m) g[i][j]=read(),mx[i][j]=0;
    		rep(j,1,m) rep(i,1,n) if(g[i][j]>g[i+1][j]||i==n) mx[i][j]=i;
    		rep(j,1,m) dwn(i,n,1) if(!mx[i][j]) mx[i][j]=mx[i+1][j];
    		rep(i,1,n)
    		{
    			tp=0;rep(j,1,m)
    			{
    				while(tp&&mx[i][s[tp]]>=mx[i][j]) tp--;
    				if(tp) l[j]=s[tp];else l[j]=0;s[++tp]=j;
    			}
    			tp=0;dwn(j,m,1)
    			{
    				while(tp&&mx[i][s[tp]]>=mx[i][j]) tp--;
    				if(tp) r[j]=s[tp];else r[j]=m+1;s[++tp]=j;
    			}
    			rep(j,1,m) ans=max(ans,(r[j]-l[j]-1)*(mx[i][j]-i+1));
    		}
    		printf("%d
    ",ans);
    	}
    }
    

    I

    根据题意,需要求是否存在(D)使得将(le D)的所有边加入后, 图上有(K)个联通块

    将边排序后,按照顺序加边并查集判断

    #include<bits/stdc++.h>
    #define inf 2139062143
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    #define MAXN 500100
    #define MOD 998244353
    #define Fill(a,x) memset(a,x,sizeof(a))
    #define rep(i,s,t) for(register int i=(s),i##end=(t);i<=i##end;++i)
    #define dwn(i,s,t) for(register int i=(s),i##end=(t);i>=i##end;--i)
    #define ren for(int i=fst[x];i;i=nxt[i])
    #define pls(a,b) (a+b)%MOD
    #define mns(a,b) (a-b+MOD)%MOD
    #define mul(a,b) (1LL*(a)*(b))%MOD
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    struct Edge{int u,v,w;}e[MAXN];
    bool operator < (Edge a,Edge b){return a.w<b.w;}
    int n,m,k,fa[MAXN],tot,ans;
    int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
    inline void merge(int u,int v){int fu=find(u),fv=find(v);if(fu!=fv) fa[fu]=fv,tot--;}
    int main()
    {
        rep(T,1,read())
        {
            scanf("%d%d%d",&n,&m,&k);rep(i,1,n) fa[i]=i;tot=n;ans=-1;
            rep(i,1,m) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
            if(n==k) {puts("0");continue;}sort(e+1,e+m+1);
            rep(i,1,m)
            {
                merge(e[i].u,e[i].v);
                if(tot<k) break;
                if((e[i].w!=e[i+1].w||i==m)&&tot==k) {ans=e[i].w;break;}
            }
            printf("%d
    ",ans);
        }
    }
    

    J

    莫队+树状数组暴力跑的非常快

    用树状数组维护当前区间里的数,外面套莫队即可

    #include<bits/stdc++.h>
    #define inf 2139062143
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    #define MAXN 100100
    #define MOD 998244353
    #define Fill(a,x) memset(a,x,sizeof(a))
    #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
    #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
    #define ren for(int i=fst[x];i;i=nxt[i])
    #define pls(a,b) (a+b)%MOD
    #define mns(a,b) (a-b+MOD)%MOD
    #define mul(a,b) (1LL*(a)*(b))%MOD
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int lim=1e5;
    int n,m,g[MAXN],bl[MAXN],sz,c[MAXN];
    int ans[MAXN],res,w[MAXN];
    struct ask{int l,r,a,b,id;}q[MAXN];
    inline void mdf(int x,int w) {if(!x) return ;for(;x<=lim;x+=x&-x) c[x]+=w;}
    inline int query(int x,int res=0) {if(!x) return 0;for(;x;x-=x&-x) res+=c[x];return res;}
    bool cmp(ask a,ask b){return bl[a.l]<bl[b.l]||(bl[a.l]==bl[b.l]&&a.r<b.r);}
    int main()
    {
    	rep(T,1,read())
    	{
    		Fill(c,0);Fill(w,0);
    	    n=read(),sz=sqrt(n);m=read();rep(i,1,n) g[i]=read()+1,bl[i]=(i-1)/sz;g[n+1]=n+1;
    	    rep(i,1,m) q[i].l=read(),q[i].a=read()+1,q[i].r=read(),q[i].b=read()+1,q[i].id=i;
    	    sort(q+1,q+m+1,cmp);int l=0,r=0;rep(i,1,m)
    	    {
    	        while(l<q[i].l) {w[g[l]]--;if(w[g[l]]==0) mdf(g[l],-1);l++;}
    	        while(l>q[i].l) {l--;w[g[l]]++;if(w[g[l]]==1) mdf(g[l],1);}
    	        while(r>q[i].r) {w[g[r]]--;if(w[g[r]]==0) mdf(g[r],-1);r--;}
    	        while(r<q[i].r) {r++;w[g[r]]++;if(w[g[r]]==1) mdf(g[r],1);}
    	        ans[q[i].id]=query(q[i].b)-query(q[i].a-1);
    	    }
    		rep(i,1,m) printf("%lld
    ",ans[i]);
    	}
    }
    

    L

    这个题限制比较多,考虑(burnside)定理,对于旋转(i)这个置换,求解其不动点个数

    有循环节个数(=gcd(i,n))即需要考虑对一个长度为(gcd(i,n))的环染色的方案

    (F(i,j))表示长度为(i)的环染(j)个绿色且相邻颜色不同的方案数

    可以先考虑将(j)个绿色先放在一些不相邻的位置,则剩余的连续空位显然只有两种填法

    (j=0)的时候根据(i)的奇偶性可能无解或有两种情况,也很显然

    (G(i,j))表示长度为(i)的环选(j)个不相邻的位置的方案数,则(F(i,j)=2^mG(n,m))

    对于(G(i,j))可以做一个简单的分类讨论

    • (n)位置不被选中时,考虑将所有绿色与后面的一个空位捆绑考虑,则存在(j)个绿色块,(i-2j)个空位,方案为(inom{i-j}{j})
    • 当选(n)时,(1)位置也一定不能选,可以不考虑(1)位置,将剩余的所有绿色与前面一个空位捆绑考虑,存在(j-1)个自由的绿色块,(i-2-2(j-1)=i-2j)个空位,方案为(inom{i-j-1}{j-1})

    加和得到(G(i,j)=inom{i-j}{j}+inom{i-j-1}{j-1})

    预处理阶乘和(2^k)之后即可(O(1))得到(F(i,j))

    现在考虑整个答案的计算:

    因为每个循环的所有颜色应当一样,故(jcdotfrac{n}{gcd(n,i)}le k)(jle lfloor frac{kcdot gcd(n,i)}{n} floor)则有:

    [egin{aligned} ans&=frac{1}{n} sumlimits_{i=1}^n sum_{j=0}^{lfloor frac{kcdot gcd(n,i)}{n} floor}F(gcd(i,n),j)\ ans&=frac{1}{n} sumlimits_{d|n} sumlimits_{i=1}^nsum_{j=0}^{lfloor frac{kd}{n} floor}F(d,j)[(i,n)==d]\ ans&=frac{1}{n} sumlimits_{d|n} sum_{j=0}^{lfloor frac{kd}{n} floor}F(d,j)sumlimits_{i=1}^n[(i/d,n/d)==1]\ ans&=frac{1}{n} sumlimits_{d|n} varphi(frac{n}{d})sum_{j=0}^{lfloor frac{kd}{n} floor}F(d,j)\ end{aligned} ]

    由于需要(dge j),否则(F(d,j))没有意义,因此计算(sum_{j=0}^{lfloor frac{kd}{n} floor}F(d,j))的时间复杂度至多为(O(d))

    (sumlimits_{d|n} d=sumlimits_{d|n}frac{n}{d}le sumlimits_{i=1}^n frac{n}{i} =nlogn)

    故可以直接枚举(d),暴力计算所有(F(d,j))

    #include<bits/stdc++.h>
    #define inf 2139062143
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    #define MAXN 1001001
    #define MOD 998244353
    #define Fill(a,x) memset(a,x,sizeof(a))
    #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
    #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
    #define ren for(int i=fst[x];i;i=nxt[i])
    #define pls(a,b) (a+b)%MOD
    #define mns(a,b) (a-b+MOD)%MOD
    #define mul(a,b) (1LL*(a)*(b))%MOD
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,k,ntp[MAXN],p[MAXN],tot,phi[MAXN],fac[MAXN],ifac[MAXN],pw2[MAXN],ans;
    int qp(int x,int t,int res=1)
    {
        for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);
        return res;
    }
    #define inv(x) qp(x,MOD-2)
    void mem(int n=1e6)
    {
        phi[1]=1;rep(i,2,n)
        {
            if(!ntp[i]) p[++tot]=i,phi[i]=i-1;
            rep(j,1,tot) if(p[j]*i>n) break;
                else
                {
                    ntp[i*p[j]]=1;
                    if(i%p[j]) phi[i*p[j]]=phi[i]*(p[j]-1);
                    else {phi[i*p[j]]=phi[i]*p[j];break;}
                }
        }
        fac[0]=pw2[0]=1;rep(i,1,n) fac[i]=mul(fac[i-1],i),pw2[i]=mul(pw2[i-1],2);
        ifac[n]=inv(fac[n]);dwn(i,n-1,0) ifac[i]=mul(ifac[i+1],i+1);
    }
    inline int C(int n,int m)
    {
        if(n<m||n<0||m<0) return 0;
        return mul(fac[n],mul(ifac[m],ifac[n-m]));
    }
    inline int F(int n,int k)
    {
        if(!k) return (n&1)?0:2;
        return mul(pw2[k],pls(C(n-k,k),C(n-k-1,k-1)));
    }
    inline int sum(int n,int k,int res=0)
    {
        rep(i,0,min(n,k)) res=pls(res,F(n,i));
        return res;
    }
    int main()
    {
        mem();rep(T,1,read())
        {
            n=read(),k=read();ans=0;
            rep(i,1,sqrt(n)) if(n%i==0)
            {
                ans=pls(ans,mul(phi[n/i],sum(i,k*i/n)));
                if(i*i!=n) ans=pls(ans,mul(phi[i],sum(n/i,k/i)));
            }
            printf("%d
    ",mul(ans,inv(n)));
        }
    }
    
  • 相关阅读:
    Django入门
    外星人入侵完整版
    外星人入侵
    简单的socket通信
    购物车程序
    列表的使用&元组
    三目运算的使用&bytes类型转str类型
    hdu 2586 How far away ?
    hdu 1075 What Are You Talking About
    洛谷 P2292 [HNOI2004]L语言
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/15081019.html
Copyright © 2011-2022 走看看