zoukankan      html  css  js  c++  java
  • NOI ONLINE部分题解

    S-2涂色问题

    CF1260C —— 双倍经验

    一眼瞪出结论(当然细节挂了)

    就比较(k)(frac {p_2-2}{p_1} +1)的大小

    (k=0)的时候显然是“NO” ——我忘了

    而且可能不互质,所以要搞个gcd ——模了几个样例才想起来

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    const int N=1000005;
    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 f*x;
    }
    int p1,p2,k;
    int gcd(int a,int b) {
    	return b?gcd(b,a%b):a;
    }
    int main() {
    	// freopen("color.in","r",stdin);
    	// freopen("color.out","w",stdout);
    	int T=read();
    	while(T--) {
    		p1=read();p2=read();k=read();
    		if(p1>p2) swap(p1,p2);
    		int g=gcd(p1,p2);
    		p1/=g;p2/=g;
    		int ans=p2%p1,res;
    		if(ans==0) res=p2/p1-1;
    		else if(ans==1) res=p2/p1;
    		else res=p2/p1+1;
    		if(k==1) puts("NO");
    		else if(k>res) puts("YES");
    		else puts("NO");
    	}
    	return 0;
    }
    
    
    

    S-2 子序列问题

    复述一下题解

    https://www.luogu.com.cn/blog/duyi/solution-p6477

    首先看到 (a[i])的范围,离散化

    朴素是枚举左右端点,再用set维护集合元素个数,瓶颈在于枚举端点。

    正解是考虑每个(a[i])的贡献区间,设(a[i])上次出现的位置为(pre[i]),那么贡献区间即为 ([ (pre[i],i] , [i,n] ])

    接下来考虑平方的问题 ————经典套路

    平方看成在这些位置中,任选出两个位置(可以重复)的方案数!

    设它们分别为((i,j))(不妨设((ileq j)))。则一对((i,j))会对多少个区间产生贡献?不难发现,数量是:

    ((i-max( ext{pre}[i], ext{pre}[j]))cdot (n-j+1)quad (i> ext{pre}[j]))

    暴力枚举 ((i,j))复杂度是(O(n^2))的。考虑优化

    如何快速求出:(sum_{i=1}^{j}max( ext{pre}[i], ext{pre}[j]))。我们用一个变量,记录(j)前面所有( ext{pre}[i])之和,则只需要把(leq ext{pre})的这部分值减去,再加上相同数量的( ext{pre}[j])即可。可以用两个树状数组,都以( ext{pre})值为下标,分别维护( ext{pre})值小于(x)( ext{pre})值之和,及其数量。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    typedef long long ll;
    const int N=1000005;
    const int P=1e9+7;
    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 f*x;
    }
    
    ll s[N],num[N];//树状数组
    int n,a[N],b[N],mp[N],pre[N];
    inline void upd(int x,int v) {for(int i=x;i<=n;i+=i&-i)s[i]+=x*v,num[i]+=v;}
    inline ll sum(int x){ll res=0;for(int i=x;i;i-=i&-i)res+=num[i]*(x+1)-s[i];return res;}
    
    int main() {
    	n=read();
    	for(int i=1;i<=n;i++) a[i]=b[i]=read();
    	sort(b+1,b+1+n);
    	int tot=unique(b+1,b+1+n)-b-1;
    	for(int i=1;i<=n;i++) {
    		a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
    		pre[i]=mp[a[i]];
    		mp[a[i]]=i;
    	}
    	ll cnt=0,ans=0;
    	for(int i=1;i<=n;i++) {
    		cnt=(cnt+i-pre[i]+2*(sum(i)-sum(pre[i]))%P+P)%P;
    		ans=(ans+cnt)%P;
    		upd(pre[i]+1,1);upd(i+1,-1);
    	}
    	printf("%lld
    ",(ans%P+P)%P);
    	return 0;
    }
    

    J-2 建设城市

    组合数学

    组合弱者——推+写 近1小时

    分类讨论

    1. (x,y)同侧
      ([x,y])看成一个球 ,就是n-(y-x) 个球放到m个盒子里 (可以空)
      剩余 n 个球,放到m个盒子里 (可以空)

    2. 异侧

    剩余 n-x个球,放到m-i+1个盒子里(可以空)
    剩余 y-1个球,放到m-i+1个盒子里(可以空)
    剩余 n-y个球,放到i个盒子里(可以空)

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    typedef long long ll;
    const int N=200005;
    const int P=998244353;
    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 f*x;
    }
    int m,n,x,y;
    ll fac[N],inv[N];
    ll qpow(ll a,ll b) {
    	ll res=1;
    	while(b) {
    		if(b&1) res=res*a%P;
    		a=a*a%P;
    		b>>=1;
    	}
    	return res;
    }
    inline ll C(int n,int m) {
    	if(n<0||n<m||m<0) return 1;
    	return fac[n]*inv[m]%P*inv[n-m]%P;
    }
    ll ans;
    int main() {
    	m=read();n=read();x=read();y=read();
    	fac[0]=1;
    	for(int i=1;i<=n+m;i++) 
    		fac[i]=fac[i-1]*i%P;
    	inv[n+m]=qpow(fac[n+m],P-2);
    	for(int i=n+m;i;i--) inv[i-1]=inv[i]*i%P;
    	if(x>y) swap(x,y);
    	if(x<=n&&y>n) {//异侧
    		y-=n;
    		for(int i=1;i<=m;i++) 
    			ans=(ans+C(x-2+i,i-1)*C(n-x+m-i,m-i)%P*C(y-1+m-i,m-i)%P*C(n-y+i-1,i-1)%P)%P;
    		printf("%lld
    ",ans);
    	}
    	else { //同侧
    		ans=C(n-(y-x)+m-1,m-1)*C(n+m-1,m-1)%P%P;
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    Effective Java 第三版——72. 赞成使用标准异常
    Effective Java 第三版——71. 避免不必要地使用检查异常
    Effective Java 第三版——70. 对可恢复条件使用检查异常,对编程错误使用运行时异常
    Effective Java 第三版——69. 仅在发生异常的条件下使用异常
    Effective Java 第三版——68. 遵守普遍接受的命名约定
    Effective Java 第三版——67. 明智谨慎地进行优化
    Effective Java 第三版——66. 明智谨慎地使用本地方法
    Effective Java 第三版——65. 接口优于反射
    Effective Java 第三版——64. 通过对象的接口引用对象
    Effective Java 第三版——63. 注意字符串连接的性能
  • 原文地址:https://www.cnblogs.com/ke-xin/p/14102391.html
Copyright © 2011-2022 走看看