无rating混合赛cpp

概述

无rating赛,顾名思义,考差不会有物质上的教训,考好也不会有物质上的奖励……
于是,我就不检查……成绩……
在这里插入图片描述


顺序

  • 1.质因数分解(普及-
  • 2.蛇形螺旋方正(普及-
  • 3.大采购(普及
  • 4.吉波那契数列(普及+
  • 5.魔塔(提高
  • 6.对战(提高

1.质因数分解

【题目大意】

输入T组数,求出他们的所有质因数

【输入格式】

第一行一个正整数T,表示数据的组数。
接下来t行,每行一个正整数n,表示待分解的数

【输出格式】

共T行
每行若干个用空格隔开的正整数,从小到大排列,表示n的质因数分解结果

【样例输入】

2
7
12

【样例输出】

7
2 2 3

【数据规模和约定】

对于%100的数据,2≤n≤1012,t≤20;

============
质因数分解,很简单啊!!
应该都要拿买分的啊……
但是,我最初代码的判断是 i ∗ i ≤ n i*i≤n iin, i i i的定义又是int,于是乎,1020就爆了int了……可怜的60分
在这里插入图片描述
改了之后的似乎正解了的代码:

#include<bits/stdc++.h>
using namespace std;
int T,len;
long long n;
long long a[1000006];
int main()
{
	freopen("prime.in","r",stdin);
	freopen("prime.out","w",stdout); 
	int i;
	scanf("%d",&T);
	while(T--)
	{
		len=0;
		scanf("%lld",&n);
		for(i=2;i<=sqrt(n)+1;++i)
		{
			if(n%i==0)
			{
			   n/=i;
			   a[++len]=i;
			   --i;
			}
		}
		for(i=0;++i<=len;)if(a[i])printf("%lld ",a[i]);
		printf("%lld\n",n);
	}
	
	
	return 0;
}

2.蛇形螺旋矩阵

【题目大意】

给出一个方正大小,同事给出每一圈从外往里的旋转的方向,输出这个矩阵(特别说明:第i圈的旋转是从( i , i i,i ii)处开始的。)

【输入格式】

第一行一个正整数n,表示矩阵的边长。
第二行 ( n + 1 ) / 2 (n+1)/2 (n+1)/2个整数,第i个数表示从外向内第 i i i圈的旋转的方向。1表示顺时针方向,-1表示逆时针方向。

【输出格式】

输出共n行,每行n个用空格隔开的正整数,第 i i i行第 j j j个整数表示这个矩阵 ( i , j ) (i,j) (i,j)处的应有的整数。

【样例输入】

7
1 -1 -1 1

【样例输出】

1 2 3 4 5 6 7
24 25 40 39 38 37 8
23 26 41 48 47 36 9
22 27 42 49 46 35 10
21 28 43 44 45 34 11
20 29 30 31 32 33 12
19 18 17 16 15 14 13

【数据规模和约定】

50%, 1 ≤ n ≤ 100 1≤n≤100 1n100
100% 1 ≤ n ≤ 1000 1≤n≤1000 1n1000

于是乎
我数组开到了100,少打了一个0 ,一个0 ,一个0!!
在这里插入图片描述
代码

#include<bits/stdc++.h>
using namespace std;
int n,m,l,x,y,k;
int a[1005],b[1005][1005];
void shunshizhen(int i,int j)
{
    for(l=i-1;++l<=n;++k)
    b[i][l]=k;
    for(l=i;++l<=n;++k)
    b[l][n]=k;
    for(l=n-1;l>=i;++k,--l)
    b[n][l]=k;
    for(l=n-1;l>i;++k,--l)
    b[l][i]=k;
}
void nishizhen(int i,int j)
{
	for(l=i-1;++l<=n;++k)
	b[l][i]=k;
	for(l=i;++l<=n;++k)
	b[n][l]=k;
	for(l=n-1;l>i;++k,--l)
	b[l][n]=k;
	for(l=n;l>i;++k,--l)
	b[i][l]=k;
}
int main()
{
    freopen("matrix.in","r",stdin);
    freopen("matrix.out","w",stdout);
	int i;
	for(scanf("%d",&n),i=0;++i<=(n+1)/2;)
        scanf("%d",&a[i]);
    int m=n;
    if(n%2)
    {
	    for(i=0,x=1,y=1,k=1;++i<=(m+1)/2;n--)
	    {
	   	    if(a[i]==-1)nishizhen(i,i);
	   	    else shunshizhen(i,i);
	    }
    }
    else
    for(i=0,x=1,y=1,k=1;++i<=(m+1)/2;n--)
	{
		/*if(i==(n+1)/2+1)
		{
			if(a[i-1]==-1)nishizhen(i,i);
	   	    else shunshizhen(i,i);
		}*/
	   	if(a[i]==-1)nishizhen(i,i);
	   	else shunshizhen(i,i);
	}
//	if(!b[i][i])b[i][i]=m*m;
	int j;
	for(i=0;++i<=m;)
	{
	  for(j=0;++j<m;)
	    printf("%d ",b[i][j]);
	  printf("%d\n",b[i][m]);
	}
	  
	return 0;
}

3.大采购

【题目大意】

w个容量,n样物品,每个物品有ai点费用,ci点价值,数量为mi,他想获得最大的价值

【输入格式】

第一行两个正整数n,w,含义见题面。
接下来n行,每行三个整数,第i+1行的整数分别表示ai,ci,mi。

【输出格式】

一行一个整数,表示最大的价值

【样例输入】

4 15
5 6 4
3 4 3
1 1 5
2 3 3

【样例输出】

21

【数据规模和约定】

100%, n ≤ 500 , w ≤ 10000 , m i ≤ 1000 , a i ≤ 100 , c i ≤ 1000 n≤500,w≤10000,mi≤1000,ai≤100,ci≤1000 n500w10000mi1000ai100ci1000

一看就是二进制优化,多重背包问题
然而我 k &lt; &lt; = 1 k&lt;&lt;=1 k<<=1却写成了 k &lt; &lt; = 2 k&lt;&lt;=2 k<<=2。爆零

在这里插入图片描述

代码呢?

#include<bits/stdc++.h>
using namespace std;
int n,m,i,j,ans,maxx,len;
const int N=500;
struct ss
{
	int v,w;
}a[N*N*2*10];
int f[N*N*2*10];
int main()
{
	freopen("shopping.in","r",stdin);
	freopen("shopping.out","w",stdout);
	for(scanf("%d%d",&n,&maxx),i=0;++i<=n;)
	{
		int x,y,z,k=1;
		scanf("%d%d%d",&x,&y,&z);
		while(k<=z)
		{
			z-=k;
			a[++len].w=x*k;
			a[len].v=y*k;
			k<<=1;
		}
		if(z)
	    {
	    	a[++len].w=x*z;
	    	a[len].v=y*z;
		}
	}
	for(i=0;++i<=len;)
	  for(j=maxx;j>=a[i].w;--j)
	    f[j]=max(f[j],f[j-a[i].w]+a[i].v);
	for(i=0;++i<=maxx;)
	  ans=max(ans,f[i]);
	printf("%d",ans);
	
	return 0;
}

4.吉波那契数列

【题目大意】

我们定义吉波那契数列为
G n = G n − 1 + G n − 2 G_n=G_n-1 +G_n-2 Gn=Gn1+Gn2
G 0 = 1 G_0=1 G0=1, G 1 G_1 G1是随机的正整数t。
现在告诉你 G i G_i Gi的值和两个正整数i,j,请你求出 G j G_j Gj.鉴于 G j G_j Gj可能很大,输出 G j m o d 19960515 G_j mod 19960515 Gjmod19960515.

【输入格式】

有多组数据。第一行是一个正整数T,表示测试数据组数。
接下来T行,每行为一组测试数据,每组测试数据包含3个正整数 i , G i , j i,G_i,j iGi,j

【输出格式】

对于每组数据,输出 G j m o d 19960515 G_j mod 19960515 Gjmod19960515.
假如没有合适的t,请输出-1.

【样例输入】

2
1 1 2
3 5 4

【样例输出】

2
8

【数据规模与约定】

100% 有 T ≤ 10000 , 1 ≤ i , j ≤ 100000 , 0 ≤ G i &lt; 19960515 T≤10000,1≤i,j≤100000,0≤G_i&lt;19960515 T10000,1i,j100000,0Gi<19960515

============
这道题之前没有推出来~
写出 G n G_n Gn的前几项:
G 0 = 1 G_0=1 G0=1
G 1 = t G_1=t G1=t
G 2 = t + 1 G_2=t+1 G2=t+1
G 3 = 2 t + 1 G_3=2t+1 G3=2t+1
G 4 = 3 t + 2 G_4=3t+2 G4=3t+2
G 5 = 5 t + 3 G_5=5t+3 G5=5t+3

系数为斐波那契数列,整理为
G n = F n − 1 t + F n − 2 G_n=F_{n-1}t+F_{n-2} Gn=Fn1t+Fn2
然后代码为

#include<bits/stdc++.h>
using namespace std;
const int MOD=19960515;
long long T,t,n,m,i,j,k,l,ll;
long long a[100005],f[100005];
int main()
{
//	freopen("gibonacci.in","r",stdin);
//	freopen("gibonacci.out","w",stdout);
   for(f[0]=0,f[1]=1,i=1;++i<=100002;)f[i]=(f[i-1]+f[i-2])%MOD;
   scanf("%lld",&T);
   while(T--)
   {
   	memset(a,0,sizeof(a));
   	a[0]=1;
       scanf("%lld",&i);
   	scanf("%lld%lld",&a[i],&j);
       a[i]-=f[i-1];	
       if(a[i]%f[i]||a[i]<=0)
       {
       	printf("-1\n");
       	continue;
   	}
   	t=(a[i]/f[i])%MOD;
   	a[j]=(f[j-1]+t*f[j])%MOD;
   	printf("%lld\n",a[j]%MOD);
   }
   return 0;
}

5.魔塔

【题目大意】

这个魔塔没有门,也没有特殊的道具,只有一种怪物和一些体力水。从出生点进入地图,你已经有H点初始体能,每打一个怪需要损耗一点体能,而吃到一个体能水可以得到5点体能。勇士每次只能向上下左右四个方向走,如果要打怪或者喝体力水,必须走到这点上。如果体力为0,我们的勇士任然可以走动,但不能打怪了。
我们希望能够尽量节省体力。为了能够更好地通关,也为了少杀生省人品,我们希望达到这层的终点时打最少的怪。现在给一张地图,请问最少打多少的怪才能走到终点、

【输入格式】

有多组数据,以EOF结束。对于每组数据:
第一行:三个整数H,N,M,表示初始体力H,以及地图有N行M列。
第二行开始的N行,描述了一个地图,其中#表示墙,M表示怪物,C表示体力水,S表示出生点,E表示地图终点“.”表示空位,详细请看样例。

【输出格式】

对于每组数据输出一行整数,表示最少需要打的怪的数量。
如果无法通关,请输出“Poor Warrior”(不含引号)

【样例输入】

5 5 6
S…MC
…M
M#####
MMMMME

【样例输出】

7

【数据规模】
够你搜索的

这题是个有点难度的搜索
设计状态f(x,y,h,ans) 表示在(x,y)时剩余h体力,打过ans个怪。
直接记忆化搜索
代码

#include<bits/stdc++.h>
using namespace std;
const int dx[5]={0,0,-1,+1};
const int dy[5]={-1,+1,0,0};
int a[5000][5000],minn=1000000000;
int v[11][11][11][11];
int pl=0,pll=0,po=0,poo=0;
int n,m,h;
void dfs(int x,int y,int h,int ans)
{
	if(ans>=minn)
	return;
	if(v[x][y][h][ans]==1)
	return;
	v[x][y][h][ans]=1;
	if(x==pl&&y==pll)
	{
		minn=min(minn,ans);
		return;
	}
	int ord[4]={0,1,2,3};
  	random_shuffle(ord,ord+4);
	for(int i=0;i<4;i++)
	{
		int xx=dx[ord[i]]+x,yy=dy[ord[i]]+y;
		if(xx<1||yy<1||xx>n||yy>m||a[xx][yy]==1)
		continue;
		else if(a[xx][yy]==2&&h>=1)
		{
			a[xx][yy]=0;
			dfs(xx,yy,h-1,ans+1);
			a[xx][yy]=2;
		}
		else if(a[xx][yy]==3)
		{
			a[xx][yy]=0;
			dfs(xx,yy,h+5,ans);
			a[xx][yy]=3;
		}
		else if(a[xx][yy]==0)
		{
			dfs(xx,yy,h,ans);
		}
	}
}
void kl()
{

		memset(v,0,sizeof(v));
	minn=1000000000;
		dfs(po,poo,h,0);

}
int main()
{
	freopen("tower.in","r",stdin);
	freopen("tower.out","w",stdout);
	while(scanf("%d%d%d",&h,&n,&m)!=EOF)
	{
			memset(a,0,sizeof(a));
				memset(v,0,sizeof(v));
		minn=1000000000;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				char x;
				cin>>x;
				if(x=='S')
				{
					po=i;
					poo=j;
				}
				if(x=='E')
				{
					pl=i;
					pll=j;
				}
				if(x=='#')
				{
					a[i][j]=1;
				}
				if(x=='.')
				{
					a[i][j]=0;
				}
				if(x=='M')
				{
					a[i][j]=2;
				}
				if(x=='C')
				{
					a[i][j]=3;
				}
			}
		}
		int ll=100000000;
		for(int i=1;i<=100;i++)
		{
			kl();
			ll=min(ll,minn);
		}
		if(minn==1000000000)
		{
			printf("Poor Warrior\n");
		}
		else
		printf("%d\n",ll);
	}
}

在这里插入图片描述在这里插入图片描述在这里插入图片描述
按顺序枚举中间点i,那么问题转换为求[1,i-1]中比a[i]小/大的数有多少个,求[i+1,n]中比a[i]小/大的数有多少个。求完之后运用乘法原理即可计算答案。
注意用树状数组,正着做一遍,反着做一遍

#include<bits/stdc++.h>
using namespace std;
long long n,t,a[100001],c[205001],la[100001],li[100001],ra[100001],ri[100001];
long long ans,maxx=-1;
int lowbit(int x){
	return x&(-x);
}
void add(int x,int y){
	while(x<=maxx){
		c[x]+=y; x+=lowbit(x);
	}
}
int getsum(int k){
	int sum=0;
	while(k>0){
		sum+=c[k]; k-=lowbit(k);
	}
	return sum;
}
signed main(){
	freopen("inhouse.in","r",stdin);
	freopen("inhouse.out","w",stdout);
	scanf("%d",&t);
	for(int j=1;j<=t;j++){
		maxx=-1;
		memset(c,0,sizeof(c)); 
		ans=0;
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]),maxx=max(maxx,a[i]);
		for(int i=1;i<=n;i++){
			li[i]=getsum(a[i]-1);
			la[i]=i-li[i]-1; 
			add(a[i],1);
		}
		memset(c,0,sizeof(c));
		for(int i=n;i>=1;i--){
			ri[i]=getsum(a[i]-1);
			ra[i]=n-ri[i]-i;
			add(a[i],1);
		}
		for(int i=2;i<n;i++)
			ans+=(1LL)*li[i]*ra[i]+(1LL)*la[i]*ri[i];
		printf("%lld\n",ans);
	}
	return 0;
}

总体来说,这次考试并不好~~

下次继续加油吧~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值