Hades_Fei & Loongint |
Day1
【Hint&P.S.】
题目名称 | Pegged | Metro | Path |
输入文件 | Pegged.in | Metro.in | Path.in |
输出文件 | Pegged.out | Metro.out | Path.out |
测试点数目 | 10 | 10 | 10 |
测试点分数 | 10 | 10 | 10 |
题目类型 | 传统 | 传统 | 传统 |
时间限制 | 1s | 1S | 1S |
空间限制 | 128MB | 128MB | 128MB |
1.C++同学禁止使用STL库,函数main()的返回值类型必须是int,程序正常结束时的返回值必须是0。
2.文件总大小不得大于50KB
3.考试评测采用Cena@WindowsSeven环境,不区分文件名的大小写。
4. 答疑请用飞鸽传书
Pegged
【Description】
Hades_Fei和他的MM都很喜欢一种叫做Pegged的游戏,这种游戏的中文名字叫做孔明棋(见KongMing_Chess.rar),但是MM觉得Hades_Fei的智商玩这种游戏太小意思了,所以她对这个游戏做了一下小小的改变,在一个无限大的棋盘的格子上有一些棋子,这些棋子构成一个M*N的矩形(M为高度,N为宽度)。请你求出最后最少能剩下几个棋子。
这可难倒了Hades_Fei,所以他需要Hzoiers的帮助…
注:孔明棋的游戏规则:你可以用一个棋子跳过另一个相邻的棋子,被跳过的棋子将被删除。
【Input Format】
本题有多组数据。对于每组数据,仅有一行,两个正整数M,N,最后一行M=N=0,无需处理此行数据。
【Output Format】
对于每组数据,一个正整数,表示最少剩下的棋子数。
【Sample Input】
3 4
0 0
【Sample Output】
2
【Data】
对于30%的数据 | N,M≤10 | Task≤2 |
对于60%的数据 | N,M≤1000 | Task≤10 |
对于100%的数据 | N,M≤100000 | Task≤100 |
#include <iostream> using namespace std; int n,m; int main(){ freopen("pegged.in","r",stdin); freopen("pegged.out","w",stdout); while (cin>>n>>m){ if (n==0 && m==0) break; if (n==1 || m==1) cout<<(m+n)/2<<endl; else if ((n*m) % 3==0) cout<<2<<endl; else cout<<1<<endl; } return 0; }
Metro
【Description】
话说Loongint要去找他的MM,可是MM住在城市的另一边,Loongint必须借助先进的交通工具——地铁来节省时间。城市为正方形格子,每个格子的边长为100米。地铁站在其中一个十字路口。Loongint要从家里步行到地铁站。他沿着街道走,也可以穿越某一些格子的对角线,这样会近一些。 求Loongint从西南角的家到东北角地铁站的最短路径。
【Input Format】
输入首行为N,M(),即东西、南北的格子数。Loongint从格子(1,1)的西南角的家出发,地铁站位于格子(N,M)的东北角。第二行为K,表示有k个格子允许对角线穿越。以下K行为允许对角线穿越的格子,分别用一对数表示,空格隔开。
【Output Format】
求Nikanor的家到地铁站的最短路径,四舍五入到整数,单位:米。
【Sample Input】
3 2
3
1 1
3 2
1 2
【Sample Output】
383
【Data】
对于30%的数据 |
N,M≤5000 |
k≤100 |
对于100%的数据 |
0<N,M≤1000000 |
k≤1000 |
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> using namespace std; int n,m,k; int tot; int q[2000]; bool v[1000100]; struct node{ int x,y; bool operator <(const node &T)const{ if (T.x!=x) return (T.x>x);else return T.y>y; } }a[3000]; int Round(double x){ if ((int)(x+0.5)==(int)x+1)return (int)x+1; return (int)x; } int find(int x){ if (q[tot]<x){ tot++; return tot; } int l=1,r=tot; while (l<r){ int mid=(l+r) >> 1; if (q[mid]<=x) l=mid+1;else r=mid; } return l; } int main(){ freopen("metro.in","r",stdin); freopen("metro.out","w",stdout); scanf("%d%d%d",&n,&m,&k); for (int i=1;i<=k;i++) scanf("%d%d",&a[i].x,&a[i].y); sort(a+1,a+k+1); for (int i=1;i<=k;i++){ if (!v[a[i].x]) if (tot==0){ v[a[i].x]=true; q[++tot]=a[i].y; }else{ v[a[i].x]=true; int j=find(a[i].y); q[j]=a[i].y; } } double ans=(n+m)*100-2*tot*100+sqrt(20000.0)*tot; printf("%d\n",Round(ans)); return 0; }
Path
【Description】
Loongint非常喜欢Dota这款游戏~但是他总是被Dota复杂的地图困扰,有时候甚至会因为地图太复杂而失去了自己Gank和Farm的节奏。所以他需要你的帮忙。
地图上一共有n个关键位置,每个关键位置有一个关键值Vi, 关键位置之间有m条双向的通路,每条通路有其通行值Ci,我们定义两关键位置之间的距离为其间的通路的通行值和加上路径上关键值最大的关键位置(包括起点终点)的关键值。
Loongint现在有Q个询问,对于每个询问,你需要告诉他a关键位置和b关键位置间的最短距离。
【Input Format】
输入第1行为三个数 n,m,q,第2行到第n+1行表示关键位置的关键值Vi,第n+2到第n+m+1行表示通路的起始位置和通行值,第n+m+2到第n+m+q+1行表示q个询问,每个询问给出a,b。
【Output Format】
输出q行,每行对应一个询问的最短距离。
【Sample Input】
5 7 2
2
5
3
3
4
1 2 3
1 3 2
2 5 3
5 3 1
5 4 1
2 4 3
3 4 4
1 4
2 3
【Sample Output】
8
9
【Data】
对于40%的数据 |
N≤40,M≤100 |
Q≤100 |
对于60%的数据 |
N≤100,M≤2500 |
Q≤1000 |
对于100%的数据 |
N≤250,M≤10,000 |
Q≤10,000;Vi,Ci≤100,000 |
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; int g[300][300],f[300][300]; int a[300],id[300]; int n,m,k; int main(){ freopen("path.in","r",stdin); freopen("path.out","w",stdout); memset(f,8,sizeof(f)); memset(g,8,sizeof(g)); scanf("%d%d%d",&n,&m,&k); for (int i=1;i<=n;i++){ scanf("%d",&a[i]); id[i]=i; g[i][i]=0; } for (int i=1;i<=n;i++){ for (int j=i+1;j<=n;j++){ if (a[id[i]]>a[id[j]]){ swap(id[i],id[j]); } } } for (int i=1;i<=m;i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); if (g[a][b]>c) g[a][b]=g[b][a]=c; } for (int t=1;t<=n;t++){ int k=id[t]; for (int i=1;i<=n;i++){ for (int j=1;j<=n;j++){ if (g[i][j]>g[i][k]+g[k][j]) g[i][j]=g[i][k]+g[k][j]; } } for (int i=1;i<=n;i++){ for (int j=1;j<=n;j++){ if (f[i][j]>g[i][j]+max(a[i],max(a[j],a[k]))) f[i][j]=g[i][j]+max(a[i],max(a[j],a[k])); } } } for (int i=1;i<=k;i++){ int a,b; scanf("%d%d",&a,&b); int ans=f[a][b]; printf("%d\n",ans); } return 0; }
Day2
塞北高原 Day Two |
Hades_Fei & Loongint |
【Hint&P.S.】
题目名称 |
Function |
Que |
FunctionAgain |
输入文件 |
Function.in |
Que.in |
FunctionAgain.in |
输出文件 |
Function.out |
Que.out |
FunctionAgain.out |
测试点数目 |
10 |
10 |
10 |
测试点分数 |
10 |
10 |
10 |
题目类型 |
传统 |
传统 |
传统 |
时间限制 |
1s |
1S |
1S |
空间限制 |
128MB |
128MB |
128MB |
1.C++同学禁止使用STL库,函数main()的返回值类型必须是int,程序正常结束时的返回值必须是0。
2.文件总大小不得大于50KB
3.考试评测采用Cena@WindowsSeven环境,不区分文件名的大小写。
4. 答疑请用飞鸽传书
Function
【Description】
我们定义如下函数: ,给出x的初始值x0,通过不断地代入x可以求得新的x'、x'',通过x'和x''代入公式又可以得到新的4个值。
给出a1,b1,d1,a2,b2,d2,初始值x0,问你迭代多次后得到的第n小的值是多少。
【Input Format】
第一行两个数,为x0和n,第二行为a1,b1,d1,第三行为a2,b2,d2。
【Output Format】
一个正整数,表示第n小的数的值。
【Sample Input】
3 10
4 3 3
17 8 2
【Sample Output】
65
【Hint】
1、c=3
2、F1(3)=4×3/3+3 :7
3、F1(7)=4×7/3+3 :12
4、F1(12)=4×12/3+3 :19
5、F1(19)=4×19/3+3 :28
6、F2(3)=17×3/2+8 :33
7、F1(28)=4×28/3+3 :40
8、F1(33)=4×33/3+3 :47
9、F1(40)=4×40/3+3 :56
10、F1(47)=4×47/3+3 :65
【Data】
对于100%的数据 |
X0≤100,N≤4000000 |
a1,b1,d1,a2,b2,d2≤20 |
涉及到的所有数字都将是整数。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; long long a1,b1,d1,a2,b2,d2; int n; long long x; long long q[5000000]; int head1,head2,tail; int main(){ freopen("function.in","r",stdin); freopen("function.out","w",stdout); scanf("%I64d%d",&x,&n); scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&a1,&b1,&d1,&a2,&b2,&d2); head1=1; head2=1; tail=1; q[1]=x; while (tail<n){ long long f1=q[head1]*a1/d1+b1; long long f2=q[head2]*a2/d2+b2; if (f1<f2 && f1>q[tail]){ q[++tail]=f1; head1++; }else if (f1>f2 && f2>q[tail]){ q[++tail]=f2; head2++; }else if (f1==f2 && f2>q[tail]){ q[++tail]=f2; head1++; head2++; }else if (f1<f2) head1++;else if (f1>f2) head2++;else{++head1;++head2;} } printf("%I64d\n",q[n]); return 0; }
Que
【Description】
给出一个n个数组成的序列,这n个数的值∈[1,m],对于一段区间,如果其中值的种类数为K,那么我们称这段区间的价值为K2。请将序列进行合适的划分,使得总价值最小。总价值为各段价值之和。
【Input Format】
第一行两个数n,m。
接下来n行,每行一个数,表示序列中每个数的值。
【Output Format】
一个数,表示总价值。
【Sample Input】
13 4
1
2
1
3
2
2
3
4
3
4
3
1
4
【Sample Output】
11
【Data】
对于30%的数据 |
N≤100,M≤100 |
序列中每个数≤100 |
对于100%的数据 |
N≤40000,M≤40000 |
序列中每个数≤99999 |
答案可能大于Maxlongint。
#include <cstdio> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> using namespace std; int min(int a,int b){return a<b?a:b;} int last[40010],a[40010],idx[40010],f[40010]; int n,m,lim; int main(){ freopen("que.in","r",stdin); freopen("que.out","w",stdout); scanf("%d%d",&n,&m); for (int i=1;i<=n;i++){ scanf("%d",&a[i]); last[i]=-1; } lim=(int)sqrt((double)n); idx[0]=1; for (int i=1;i<=n;i++){ int k=last[a[i]]; int j=0; while (j<=lim && idx[j]-1!=k) j++; j--; for (int k=j;k>=0;k--) idx[k+1]=idx[k]; f[i]=i; for (int j=1;j<=lim;j++){ if (idx[j]==0) break; f[i]=min(f[i],f[idx[j]-1]+j*j); } idx[0]++; last[a[i]]=i; } printf("%d\n",f[n]); return 0; }
FunctionAgain
【Description】
对于一个递归函数w(a,b,c)。如果a<=0 or b<=0 or c<=0就返回值1。如果a>20 or b>20 or c>20就返回w(20,20,20)。如果a<b并且b<c 就返回w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c),其它别的情况就返回w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1),这是个简单的递归函数,但实现起来可能会有些问题。
【Input Format】
会有若干行.每行三个数,表示a,b,c。并以-1,-1,-1结束.
【Output Format】
输出若干行,注意各种中的空格。
【Sample Input】
1 1 1
2 2 2
-1 -1 -1
【Sample Output】
w(1, 1, 1) = 2
w(2, 2, 2) = 4
【Data】
对于100%的数据 |
a,b,c<30 |
Task<11 |
#include <cstdio> #include <iostream> #include <cstring> using namespace std; int a,b,c; long long f[50][50][50]; int W(int x,int y,int z){ if (x<=0 || y<=0 || z<=0) return 1; if (x>20 || y>20 || z>20) return W(20,20,20); if (f[x][y][z]!=-1) return f[x][y][z]; if (x<y && y<z){ f[x][y][z]=W(x,y,z-1)+W(x,y-1,z-1)-W(x,y-1,z); return f[x][y][z]; }else{ f[x][y][z]=W(x-1,y,z)+W(x-1,y-1,z)+W(x-1,y,z-1)-W(x-1,y-1,z-1); return f[x][y][z]; } } int main(){ freopen("functionagain.in","r",stdin); freopen("functionagain.out","w",stdout); memset(f,-1,sizeof(f)); while (scanf("%d%d%d",&a,&b,&c)!=EOF){ if (a==-1 && b==-1 && c==-1) break; long long ans=W(a,b,c); printf("w(%d, %d, %d) = %I64d\n",a,b,c,ans); } return 0; }