• [四校联考]Easy Problems


    简单计数

    Description
    对于两个\(1\)~\(n\)的排列\(a,b\),定义\(orz(a,b)=max(a_1,b_1)+\)...\(+max(a_n,b_n)\)
    你需要求出有多少对\((a,b)\)满足\(orz(a,b)\;\geq\;m\)
    Input
    一行两个正整数\(n,m\)
    Output
    一行一个整数表示答案。对\(998244353\)取模。
    Sample Input

    3 8
    

    Sample Output

    18
    

    HINT
    \(1\;\leq\;n\;\leq\;50,1\;\leq\;m\;\leq\;2500\)
    Solution

    假设\(a_i=i\),\(f[i][j][k]\)表示\(b\)中已填了\(1\)$i$,其中有$j$个填在$1$\(i\),满足\(max(a_i,b_i)\;\leq\;i\)\(\sum\;max(a_i,b_i)=k\).

    分在第\(i\)个位置填\(i\)、把\(i\)放在\(1\)$i-1,i$放$<i$的数、把$i$放在$1$\(i-1,i\)\(>i\)的数、把\(i\)放在\(i+1\)$n,i$放$<i$的数、把$i$放在$i+1$\(n,i\)\(>i\)的数五种情况考虑:
    \(f[i][j][k]=f[i-1][j-1][k-i]\)
    \(\;\;\;\;\;\;\;\;\;\;\;\;\;\;+f[i-1][j-2][k-i\times2]\times[(i-1)-(j-2)]\)
    \(\;\;\;\;\;\;\;\;\;\;\;\;\;\;+f[i-1][j-1][k-i]\times[(i-1)-(j-1)]\)
    \(\;\;\;\;\;\;\;\;\;\;\;\;\;\;+f[i-1][j-1][k-i]\times[(i-1)-(j-1)]\)
    \(\;\;\;\;\;\;\;\;\;\;\;\;\;\;+f[i-1][j][k]\)
    最后\(\times\;n!\)即为答案.

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 55
    #define M 1901
    #define K 998244353ll
    using namespace std;
    typedef long long ll;
    int n,m,mx;
    ll f[N][N][M],mul=1ll,ans;
    inline ll sqr(int k){
    	return (ll)(k*k);
    }
    inline void Aireen(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i)
    		mul=mul*(ll)(i)%K;
    	f[0][0][0]=1;
    	for(int i=1;i<=n;++i)
    		for(int j=0;j<=i;++j)
    			for(int k=0;k<M;++k){
    				if(j&&k>=i) f[i][j][k]=(f[i][j][k]+f[i-1][j-1][k-i])%K;
    				if(j>=2&&k>=(i<<1)) f[i][j][k]=(f[i][j][k]+f[i-1][j-2][k-(i<<1)]*sqr(i-j+1)%K)%K;
    				if(j&&k>=i) f[i][j][k]=(f[i][j][k]+f[i-1][j-1][k-i]*(ll)(i-j)%K)%K;
    				if(j&&k>=i) f[i][j][k]=(f[i][j][k]+f[i-1][j-1][k-i]*(ll)(i-j)%K)%K;
    				f[i][j][k]=(f[i][j][k]+f[i-1][j][k])%K;
    			}
    	for(int i=m;i<M;++i){
    		ans=(ans+f[n][n][i]*mul)%K;
    	}
    	printf("%lld\n",ans); 
    }
    int main(){
    	freopen("easycount.in","r",stdin);
    	freopen("easycount.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    简单几何

    Description
    给定\(n\)个白点和\(m\)个黑点,你需要求出有多少个相邻点异色的
    凸四边形。点的坐标为\([1,10^7]\)中的整数。 保证不存在两个点坐标相同,也不存在三点共线。
    Input
    第一行两个正整数\(n,m\)
    接下来\(n+m\)行每行两个整数\(x,y\)表示坐标。前\(n\)行为白点,后\(m\)行为黑点。
    Output
    一行一个整数表示答案。
    Sample Input

    5 5
    7612781 7923905
    390883 6554981
    8816160 3805981
    4131888 3855473
    4491640 5239819
    998553 2850237
    5957016 3387077
    8511547 701391
    8935990 677435
    3706758 5650977
    

    Sample Output

    18
    

    HINT
    \(n,m\;\leq\;400\)
    Solution
    相邻点异色的四边形个数-相邻点异色的凹四边形个数.
    相邻点异色的四边形个数:两白点所在直线的一侧黑点个数\(\times\)另一侧黑点个数.
    相邻点异色的凹四边形个数:枚举白点,再枚举两个黑点,此时在图中区域\(1\)的白点都会和它们构成一个凹四边形.枚举白点后,将每个黑点与此白点连线的反向延长线和其他白点与此白点的连线按极角排序,分类讨论用加减法及前缀和求解.(延长线所成角跨不跨越极角为\(0\)的向量)

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 405
    #define eps 1e-13
    using namespace std;
    typedef long long ll;
    const double pi=acos(-1);
    struct point{
    	int x,y;
    }a[N],b[N];
    struct cnt{
    	int s;double w;
    }p[N+N]; 
    int n,m,sum;ll ans;
    inline bool cmp(cnt x,cnt y){
    	return x.w<y.w;
    }
    inline point dec(point x,point y){
    	return (point){x.x-y.x,x.y-y.y};
    }
    inline int mul(point x,point y){
    	ll k=(ll)(x.x)*(ll)(y.y)-(ll)(y.x)*(ll)(x.y);
    	if(!k) return 0;
    	if(k<0ll) return -1;
    	return 1;
    }
    inline void Aireen(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i)
    		scanf("%d%d",&a[i].x,&a[i].y);
    	for(int i=1;i<=m;++i)
    		scanf("%d%d",&b[i].x,&b[i].y);
    	for(int i=1;i<n;++i)
    		for(int j=i+1;j<=n;++j){
    			sum=0;
    			for(int k=1;k<=m;++k)
    				if(mul(dec(b[k],a[i]),dec(a[j],a[i]))>0) ++sum;
    			ans+=(ll)(sum*(m-sum));
    		}
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=m;++j){
    			p[j].w=atan2(b[j].y-a[i].y,b[j].x-a[i].x);
    			if(p[j].w>0.0) p[j].w-=pi;
    			else p[j].w+=pi;
    		}
    		sort(p+1,p+1+m,cmp);
    		for(int j=1;j<=m;++j){
    			p[j].s=0;
    			for(int k=1;k<j;++k)
    				if(p[j].w-p[k].w<pi) ++p[j].s;
    				else{
    					--p[j].s;ans-=(ll)(n-1);
    				} 
    			for(int k=j+1;k<=m;++k)
    				if(p[k].w-p[j].w<pi) --p[j].s;
    				else ++p[j].s;
    		}
    		for(int j=1;j<i;++j){
    			p[j+m].s=N;p[j+m].w=atan2(a[j].y-a[i].y,a[j].x-a[i].x);
    		}
    		for(int j=i+1;j<=n;++j){
    			p[j+m-1].s=N;p[j+m-1].w=atan2(a[j].y-a[i].y,a[j].x-a[i].x);
    		}
    		sort(p+1,p+m+n,cmp);sum=0;
    		for(int j=1;j<n+m;++j){
    			if(p[j].s==N) ++sum;
    			else ans-=(ll)(sum*p[j].s);
    		}
    	}
    	printf("%lld\n",ans);
    }
    int main(){
    	freopen("easygeom.in","r",stdin);
    	freopen("easygeom.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    简单01串

    Description
    给定一个长度为\(n\)\(01\)串以及正整数\(m\)
    你可以进行以下两种操作:

    1. \(01\)串某一位取反;
    2. \(01\)串前\(k\;\times\;m\)位取反(\(k\)为整数且\(0<k\;\times\;m\;\leq\;n\)

    你需要求出至少要进行多少次操作可以使这个\(01\)串的前\(n-m\)位与后 n-m 位相同。
    Input
    第一行两个整数\(n,m\)
    第二行一个长度为\(n\)\(01\)串。
    Output
    一行一个整数表示答案。
    Sample Input

    12 3
    010011001101
    

    Sample Output

    3
    

    HINT
    \(n\;\leq\;300,m\;\leq\;55\)
    Solution
    题意等价于让\(01\)串变成每\(m\)位一循环所需最少步数.
    显然\(O(n\times2^{\sqrt{n}})\)的复杂度可以接受.
    分两种情况:
    \(1.m\leq\sqrt{n},\)枚举循环节的\(01\)串,\(DP\)出每一段所需最少改变次数,\(f[i][0/1]\)表前第\(i\)段是否取反所需最少步数,不足\(m\)的那一段直接判断.
    \(k\)表示不娶反所需改变次数,
    \(f[i][0]=min(f[i-1][0],f[i-1][1])+k,\)
    \(f[i][1]=min(f[i-1][0]+min(2,(i-1)m),f[i-1][1])+m-k\).
    \(2.m>\sqrt{n}\)枚举每一段是否取反,贪心判断\(mod\;m\)相同的位变成相同所需最少改变次数.

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 305
    using namespace std;
    typedef long long ll;
    int f[N][2],g[N],a[N],b[N],n,m,sum,ans,cnt;
    bool flag;char ch[N];
    inline void dfs2(int u,int s,int f){
    	if(u<0){
    		int cnt=0;
    		for(int i=0,k,l=n-n%m;i<m;++i){
    			k=0;flag=false;
    			for(int j=i;j<n;j+=m){
    				if(j>=l) flag=true;
    				if(a[j]^g[j/m]) ++k;
    			}
    			if(flag) cnt+=min(n/m+1-k,k);
    			else cnt+=min(n/m-k,k);
    		}
    		ans=min(ans,cnt+s);
    		return;
    	}
    	g[u/m]=f;
    	dfs2(u-m,s,f);
    	g[u/m]=f^1;
    	dfs2(u-m,s+1,f^1);
    }
    inline void dfs1(int u){
    	if(u==m){
    		int cnt=0;
    		memset(g,0,sizeof(g));
    		for(int l=0,j;l<n;l+=m){
    			j=l/m;
    			for(int i=l;i<l+m&&i<n;++i)
    				if(a[i]!=b[i%m]) ++g[j];
    			if(n-l<m){
    				cnt=min(n%m-g[j],g[j]);
    			} 
    			else if(!l){
    				f[l][0]=g[j];f[l][1]=m-g[j]+1;
    			}
    			else{
    				f[j][0]=min(f[j-1][0],f[j-1][1])+g[j];
    				f[j][1]=min(f[j-1][0]+min(2,l),f[j-1][1])+m-g[j];
    			}
    		}
    		ans=min(ans,min(f[(n-n%m-1)/m][0],f[(n-n%m-1)/m][1])+cnt); 
    		return;
    	}
    	b[u]=0;dfs1(u+1);
    	b[u]=1;dfs1(u+1);
    }
    inline void Aireen(){
    	scanf("%d%d",&n,&m);
    	scanf("%s",ch);
    	for(int i=0;i<n;++i){
    		a[i]=ch[i]-'0';
    		if(a[i]) ++ans;
    	}
    	ans=min(ans,n-ans);
    	if(m<=17) dfs1(0);
    	else dfs2(n-n%m,0,0);
    	printf("%d\n",ans);
    }
    int main(){
    	freopen("easy01.in","r",stdin);
    	freopen("easy01.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    2017-01-26 19:18:31

  • 相关阅读:
    linux 的 sftp 和 scp
    ssky-keygen + ssh-copy-id 无密码登陆远程LINUX主机
    shell入门基础必备
    通杀所有系统的硬件漏洞?聊一聊Drammer,Android上的RowHammer攻击
    APP漏洞扫描器之本地拒绝服务检测详解
    “九头虫”病毒技术分析报告
    CSP的今世与未来
    2016云栖大会即将开幕,阿里聚安全邀您共同见证盛典
    Android安全开发之安全使用HTTPS
    iOS冰与火之歌(番外篇)
  • 原文地址:https://www.cnblogs.com/AireenYe/p/15601053.html
Copyright © 2020-2023  润新知