哈尔滨理工大学2016级新生程序设计全国邀请赛

题目链接:点我点我(2293-2303)

A 棋盘村

简单dp

dp[1][1]=1

dp[i][j]=dp[i-1][j]+dp[i][j-1]

判掉强盗能到的地方即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll vis[25][25];
int main(){
	ll t;
	scanf("%lld",&t);
	while(t--){
		ll i,j,n,m,x,y;
		memset(vis,0,sizeof(vis));
		scanf("%lld%lld%lld%lld",&n,&m,&x,&y);
		n++;
		m++;
		x++;
		y++;
		if(x-2>=0&&y-1>=0)vis[x-2][y-1]=-1;
		if(x-1>=0&&y-2>=0)vis[x-1][y-2]=-1;
		if(x-2>=0)vis[x-2][y+1]=-1;
		if(x-1>=0)vis[x-1][y+2]=-1;
		if(y-2>=0)vis[x+1][y-2]=-1;
		if(y-1>=0)vis[x+2][y-1]=-1;
		vis[x+2][y+1]=-1;
		vis[x+1][y+2]=-1;
		vis[x][y]=-1;
		if(vis[1][1]!=-1){
			vis[1][1]=1;
			for(i=1;i<=n;i++){
				for(j=1;j<=m;j++){
					if(vis[i][j]==-1)continue;
					if(vis[i-1][j]!=-1)vis[i][j]+=vis[i-1][j];
					if(vis[i][j-1]!=-1)vis[i][j]+=vis[i][j-1];
				}
			}
		}
		printf("%lld\n",vis[n][m]);
	}
	return 0;
}


B 修建传送门

首先左传送门肯定放在1位置  不然会多走1到左传送门的距离

所以可以利用双指针  枚举右传送门的位置  进而找出折中点  更新ans即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll sum[100005];
int main(){
	ll t;
	scanf("%lld",&t);
	while(t--){
		ll n,i,j,x;
		scanf("%lld",&n);
		memset(sum,0,sizeof(sum));
		for(i=2;i<=n;i++){
			scanf("%lld",&x);
			sum[i]+=sum[i-1]+x;
		}
		ll zhe=1,ans=1;
		for(i=1;i<=60;i++)ans*=2;
		for(i=2;i<=n;i++){
			ll d=min(ans,sum[n]-sum[i]);
			while(zhe!=n-1&&max(sum[i]-sum[zhe+1],sum[zhe]-sum[1])>max(sum[i]-sum[zhe+2],sum[zhe+1]-sum[1]))zhe++;
			d=max(sum[zhe]-sum[1],d);
			d=max(sum[i]-sum[zhe+1],d);
			ans=min(ans,d);
		}
		if(n==1)ans=0;
		cout<<ans<<endl;
	}
	return 0;
}


C 方方正正

首先行列和不相同肯定不行

其次如果行上的最大值如果大于列的非零值的个数也不行  列同理

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int row[100005],col[100005];
int main(){
	int i,j,r,c;
	while(scanf("%d%d",&r,&c)!=EOF){
		ll rsum=0,csum=0;
		ll numr,numc,maxc,maxr;
		maxr=maxc=numr=numc=0;
		for(i=1;i<=r;i++){
			scanf("%d",&row[i]);
			rsum+=row[i];
			if(row[i]>0)numr++;
			if(row[i]>maxr)maxr=row[i];
		}
		for(i=1;i<=c;i++){
			scanf("%d",&col[i]);
			csum+=col[i];
			if(col[i]>0)numc++;
			if(col[i]>maxc)maxc=col[i];
		}
		int flag=1;
		if(rsum!=csum)flag=0;
		if(numc<maxr||numr<maxc)flag=0;
		if(flag)printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

D 陈月亮的数学题

我们知道可以将一个数N分解成 N=pa11pa22pa33pann ,其中 Pi 为素数。这样N的因子个数为 (a1+1)(a2+1)(a3+1)(ak+1)=ki=1(ai+1) 。 
所以N的所有因子的因子个数为 ki=1(1+2+3++ai+1)=ki=1(1+ai+1)(ai+1)2 ,但这只是 S=n1+n2+n3++nk 。 
所以,我们可以从 1+2+3++n=(1+n)n2 。 
12+22+32++n2=(2+n)(1+n)n6  
13+23+33++n3=((1+n)n2)2 中得到启示。 
所以最终 S=n31+n32+n33++n3k 的答案为 ki=1((1+ai+1)(ai+1)2)2

膜一发神犇的题解。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int prime[100005],num[100005],cnt=0;
void init(){
	for(int i=2;i<=65536;i++){  
		if(!prime[i])num[++cnt]=i;  
 		for(int j=2;j*i<=65536;j++){  
			prime[j*i]=1;  
            if(!(i%j)) break;  
        }
	}
}  
int main(){
	int t;
	init();
	scanf("%d",&t);
	while(t--){
		int n;
		scanf("%d",&n);
		ll ans=1;
		for(int i=1;i<=cnt;i++){
			if(n%num[i]==0){
				int s=0;
				while(n%num[i]==0){
					n/=num[i];
					s++;
				}
				ll temp=(2+s)*(1+s)*(2+s)*(1+s)/4;
				ans*=temp;
			}
		}
		if(n>1)ans*=9;
		cout<<ans<<endl;
	}
	return 0;
}

E Nine Digits

康拓展开后bfs即可  但是这样会超时

所以可以先处理出原序列能到的地方  然后每次询问查询康拓展开

原来是顺时针  所以预处理时候用逆时针

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<deque>
using namespace std;
deque<int>sp;
int fac[] = {1,1,2,6,24,120,720,5040,40320,362880},vis[362999];
int kangtuo(int a[])  {  
    int i,j,t,sum;  
    sum=0;  
    for(i=0;i<9;++i)  {  
        t=0;  
        for(j=i+1;j<9;++j)  
            if(a[i]>a[j])sum+=fac[9-i-1];  
    }  
    return sum+1;  
}
int s[20];
void reverse_kangtuo(int k){  
    int i,j,t,vst[9]={0};  
    --k;  
    for(i=0;i<9;i++){  
        t=k/fac[9-i-1];  
        for(j=1;j<=9;j++)  
			if(!vst[j]){
				if(t==0)break;  
                --t;  
            }  
        s[i]=j;  
        vst[j]=1;  
        k%=fac[9-i-1];
	}  
}  
int main(){
	memset(vis,-1,sizeof(vis));
	int m=1;
	vis[1]=0;
	int f;
	sp.push_back(m);
	while(!sp.empty()){
		f=sp.front();
		sp.pop_front();
		reverse_kangtuo(f);
		swap(s[3],s[0]);
		swap(s[4],s[0]);
		swap(s[1],s[0]);
		m=kangtuo(s);
		if(vis[m]==-1){
			vis[m]=vis[f]+1;
			sp.push_back(m);
		}
		swap(s[1],s[0]);
		swap(s[4],s[0]);
		swap(s[3],s[0]);
		swap(s[1],s[4]);
		swap(s[1],s[5]);
		swap(s[1],s[2]);
		m=kangtuo(s);
		if(vis[m]==-1){
			vis[m]=vis[f]+1;
			sp.push_back(m);
		}
		swap(s[1],s[2]);
		swap(s[1],s[5]);
		swap(s[1],s[4]);
		swap(s[3],s[6]);
		swap(s[3],s[7]);
		swap(s[3],s[4]);
		m=kangtuo(s);
		if(vis[m]==-1){
			vis[m]=vis[f]+1;
			sp.push_back(m);
		}
		swap(s[3],s[4]);
		swap(s[3],s[7]);
		swap(s[3],s[6]);
		swap(s[4],s[7]);
		swap(s[4],s[8]);
		swap(s[4],s[5]);
		m=kangtuo(s);
		if(vis[m]==-1){
			vis[m]=vis[f]+1;
			sp.push_back(m);
		}
	}
	while(scanf("%d%d%d%d%d%d%d%d%d",&s[0],&s[1],&s[2],&s[3],&s[4],&s[5],&s[6],&s[7],&s[8])!=EOF){
		int f=kangtuo(s);
		printf("%d\n",vis[f]);
	}
	return 0;
}

F Diamond

不会。。。

G FBI Tree

递归处理前缀和即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 1<<10
int a[maxn+5],sum[maxn+5];
void build(int l,int r){
	int p=sum[r]-sum[l-1];
	if(l!=r){
		int len=r-l+1;
		if(len%2){
			build(l,(r+l)/2-1);
			build((r+l)/2+1,r);
		}
		else{
			build(l,(r+l)/2);
			build((r+l)/2+1,r);
		}
	}
	if(p==0)printf("B");
	else if(p==r-l+1)printf("I");
	else printf("F");
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int i,n;
		scanf("%d",&n);
		int len=1<<n;
		for(i=1;i<=len;i++){
			scanf("%1d",&a[i]);
			sum[i]=sum[i-1]+a[i];
		}
		build(1,len);
		printf("\n");
	}
	return 0;
}

H 下雪啦

hash后存到vector里面  然后暴力匹配同一个集合里面的雪花

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
vector<int>sp[90005];
const int mod=90001;
int snow[1000005][7];
int judge(int a,int b){
	for(int i=0;i<6;i++){
		if((snow[a][0]==snow[b][i]&&
			snow[a][1]==snow[b][(i+1)%6]&&
			snow[a][2]==snow[b][(i+2)%6]&&
			snow[a][3]==snow[b][(i+3)%6]&&
			snow[a][4]==snow[b][(i+4)%6]&&
			snow[a][5]==snow[b][(i+5)%6])
			||
			(snow[a][0]==snow[b][i]&&
			snow[a][1]==snow[b][(i+5)%6]&&
			snow[a][2]==snow[b][(i+4)%6]&&
			snow[a][3]==snow[b][(i+3)%6]&&
			snow[a][4]==snow[b][(i+2)%6]&&
			snow[a][5]==snow[b][(i+1)%6]))
			return true;
	}
	return false;
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n,i,j,flag=0;
		scanf("%d",&n);
		for(i=1;i<=n;i++){
			for(j=0;j<6;j++)scanf("%d",&snow[i][j]);
		}
		for(i=0;i<=90000;i++)sp[i].clear();
		for(i=1;i<=n;i++){
			int sum=0;
			for(j=0;j<6;j++)sum+=snow[i][j];
			sum%=mod;
			for(j=0;j<sp[sum].size();j++){
				if(judge(sp[sum][j],i)){
					flag=1;
					break;
				}
			}
			if(flag)break;
			sp[sum].push_back(i);
		}
		if(flag)printf("Twin snowflakes found.\n");
		else printf("No two snowflakes are alike.\n");
	}
	return 0;
}

I 行编辑器

水题  处理个指针就行了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char s[1000005],ans[1000005];
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%s",s+1);
		int d=0,i;
		int len=strlen(s+1);
		for(i=1;i<=len;i++){
			if(s[i]=='#')d=max(0,d-1);
			else if(s[i]=='@')d=0;
			else ans[++d]=s[i];
		}
		for(i=1;i<=d;i++)printf("%c",ans[i]);
		printf("\n");
	}
	return 0;
}

J Another Tree

建树 然后随便找个结点搜  两个点的异或距离为两个点到根节点的异或距离异或起来  根据这个性质dfs搜下去即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int head[500005],cnt,tree[1000005],k;
struct node{
	int to,cap,nex;
}edge[1000005];
void add(int u,int v,int w){
	edge[cnt].to=v;
	edge[cnt].cap=w;
	edge[cnt].nex=head[u];
	head[u]=cnt++;
}
ll ans;
void dfs(int t,int d,int sum){
	ans+=tree[sum^k];
	tree[sum]++;
	for(int i=head[d];~i;i=edge[i].nex){
		int v=edge[i].to;
		if(v!=t){
			dfs(d,v,sum^edge[i].cap);
		}
	}
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		memset(head,-1,sizeof(head));
		memset(tree,0,sizeof(tree));
		cnt=0;
		int x,y,z,n,i;
		scanf("%d%d",&n,&k);
		for(i=1;i<n;i++){
			scanf("%d%d%d",&x,&y,&z);
			x++;
			y++;
			add(x,y,z);
			add(y,x,z);
		}
		ans=0;
		dfs(1,1,0);
		printf("%lld\n",ans);
	}
	return 0;
}

L 小明和字符串

水题。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char s[55];
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%s",s+1);
		int i,j,k,len=strlen(s+1);
		for(i=1;i<=len;i++){
			int now=0;
			for(j=i+1;j<=len;j++){
				if(!(s[j]>='0'&&s[j]<='9'))break;
				now+=s[j]-'0';
			}
			for(k=1;k<=now+1;k++)printf("%c",s[i]);
			i=j-1;
		}
		printf("\n");
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值