zoukankan      html  css  js  c++  java
  • noip模拟测试38

    这两天考试觉得自己不在状态,做题也没有什么思路,休整一下,尽快恢复状态。

    T1 a

    这道题,考试的时候我一直认为要用线段树,可是自己不会用,还不断的hack掉自己的线段树思路,最后没办法只能打了一个\(m^2*n^2\)的暴力,加上一些特殊性质,本来能拿50分,结果自己没有考虑周到,在测试点分治的时候没弄好,把那个二级数据直接略过了,导致只拿了30分。而正解的思路就是在暴力的基础上优化掉一个m,达到 \(n^2*m\),具体做法就是我们只枚举左上角的顶点,因为满足要求的右下角顶点必定在一个单调递增的区间中,所以满足决策单调性,可以使用二分在log的时间内算出合法的区间数,但是需要加上一些剪枝优化,具体实现见代码:

    AC_code
    #include<bits/stdc++.h>
    #define re register int
    #define ii inline int
    #define iv inline void
    using namespace std;
    const int N=5e4+10;
    const int INF=1e7+10;
    int n,m;
    long long ans;
    char s[35][N];
    int sum[35][N];
    ii read()
    {
    	int x=0;
    	bool f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-')
    			f=0;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return f?x:(-x);
    }
    signed main()
    {
    	int l,r;
    	n=read();
    	m=read();
    	for(re i=1;i<=n;i++)
    		scanf("%s",s[i]+1);
    	l=read();
    	r=read();
    	for(re i=1;i<=n;i++)
    	{
    		for(re j=1;j<=m;j++)
    		{
    			sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
    			if(s[i][j]=='1')
    				sum[i][j]+=1;
    		}
    	}
    	int L,R,nl,nr;
    	for(re i=1;i<=n;i++)
    	{
    		for(re k=i;k<=n;k++)
    		{
    		  for(re j=1;j<=m;j++)
    		  {
    				if(sum[k][m]-sum[i-1][m]-sum[k][j-1]+sum[i-1][j-1]<l || sum[k][j]-sum[i-1][j]-sum[k][j-1]+sum[i-1][j-1] >r) continue;
    				L=j,R=m,nl=m+1,nr=m+1;
    				if(sum[k][j]-sum[i-1][j]-sum[k][j-1]+sum[i-1][j-1]>=l) nl=j; 
    				else 
    					while(L<=R)
    					{
    						int mid=(L+R)>>1;
    						if(sum[k][mid]-sum[i-1][mid]-sum[k][j-1]+sum[i-1][j-1]>=l)
    						{
    							nl=mid;
    							R=mid-1;
    						}
    						else
    							L=mid+1;
    					}
    				L=j,R=m;
    				if(sum[k][m]-sum[i-1][m]-sum[k][j-1]+sum[i-1][j-1]<=r) nr=m;
    				else
    					while(L<=R)
    					{
    						int mid=(L+R)>>1;
    						if(sum[k][mid]-sum[i-1][mid]-sum[k][j-1]+sum[i-1][j-1]<=r)
    						{
    							nr=mid;
    							L=mid+1;
    						}
    						else
    							R=mid-1;
    					}
    				ans+=nr-nl+1;
    			}
    		}
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    

    T2 b

    思路:这里记 a 的最大值为 x。
    将问题转化为“对 \(i∈[1,1e5]\),求多少种选择方案使得 \(gcd=i\)
    继续转化为“对 \(i∈[1,1e5]\),求多少种选择方案使得 \(i|gcd\),
    等价于对\(i∈[1,1e5]\),求多少种选择方案使得选的所有数均为 i 的倍数
    我们预处理出\(cnt_{i,j}\)表示第 i 行中有多少个数是 j 的倍数,
    那么答案就是\(∏\limits_{i=1}^n = (cnt_{i,j} + 1) − 1\)
    最后注意去重,所以我们要倒序枚举,每次去掉出现过的当前数的倍数的答案,具体实现见代码:

    AC_code
    #include<bits/stdc++.h>
    #define int long long
    #define re register int
    #define ii inline int
    #define iv inline void
    #define lc (rt<<1)
    #define rc (rt<<1|1)
    #define mid ((l+r)>>1)
    using namespace std;
    const int mo=1e9+7;
    const int N=1e5+10;
    int n,m,maxx,ans;
    int a[30][N];
    int to[30][N],cnt[30][N];
    int an[N];
    ii read()
    {
    	int x=0;
    	bool f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-')
    			f=0;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return f?x:(-x);
    }
    signed main()
    {
    	n=read();
    	m=read();
    	for(re i=1;i<=n;i++)
    	{
    		for(re j=1;j<=m;j++)
    		{
    			a[i][j]=read();
    			maxx=max(maxx,a[i][j]);
    			to[i][a[i][j]]++;
    		}
    	}
    	for(re i=1;i<=n;i++)
    	{
    		for(re j=1;j<=maxx;j++)
    			for(re k=1;k*j<=maxx;k++)
    				cnt[i][j]+=to[i][j*k];
    	}
    	for(re i=maxx;i;i--)
    	{
    		an[i]=1;
    		for(re j=1;j<=n;j++)
    			an[i]=(an[i]%mo*(cnt[j][i]+1))%mo;
    		an[i]--;
    		for(re j=2;j*i<=maxx;j++)
    			an[i]-=an[j*i];
    		ans=(ans%mo+an[i]%mo*i%mo+mo)%mo;
    	}		
    	printf("%lld\n",(ans%mo+mo)%mo);
    	return 0;
    }
    
    
  • 相关阅读:
    ==和equals
    instanceof和相关函数
    格式化输出
    [转]使用String的intern方法节省内存
    [转]请别再拿“String s = new String("xyz");创建了多少个String实例”来面试了吧
    Go编程语言学习笔记
    [javascript]什么是闭包?
    [javascript]彻底理解 JS 中 this 的指向
    constrained属性
    Python python 数据类型的相互转换
  • 原文地址:https://www.cnblogs.com/WindZR/p/15138973.html
Copyright © 2011-2022 走看看