概述
无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
i∗i≤n,
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 i,i)处开始的。)
【输入格式】
第一行一个正整数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
1≤n≤100
100%
1
≤
n
≤
1000
1≤n≤1000
1≤n≤1000
于是乎
我数组开到了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 n≤500,w≤10000,mi≤1000,ai≤100,ci≤1000。
一看就是二进制优化,多重背包问题
然而我
k
<
<
=
1
k<<=1
k<<=1却写成了
k
<
<
=
2
k<<=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=Gn−1+Gn−2
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
i,Gi,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 < 19960515 T≤10000,1≤i,j≤100000,0≤G_i<19960515 T≤10000,1≤i,j≤100000,0≤Gi<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=Fn−1t+Fn−2
然后代码为
#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;
}
总体来说,这次考试并不好~~