主题:第63次编程比赛
plane [专家分:310] 发布于 2008-01-23 11:41:00
大家都快放假了,春节也临近,所以弄两道比较简单的题目,希望大家喜欢。
[em11][em11]
1.Stan是个懒惰的孩子,他做任何事总希望能找到既省力又快捷的方法。Stan的父母开着一家餐馆。餐馆有n*n张桌子,排放成n*n的方阵,每个桌子都有一个坐标,左上角的桌子的坐标为(1,1),其右面的桌子坐标为(1,2),其下面的桌子的坐标为(2,1).....最右下角桌子的坐标为(n,n)。Stan每天都要帮助他父母擦桌子,他当然不打算自己一个人干,所以他召唤出了一只小精灵。
小精灵只有一项技能:当Stan擦了坐标为(x,y)的桌子时,小精灵会自动帮他把所有坐标为(kx,ky)(k=2,3,.........,,使得kx<=n,且ky<=n)的这些桌子擦干净。现在,Stan想知道对于n*n张桌子,他最少需要擦多少张桌子就能把桌子全部擦干净。
比如n=4时,Stan只要擦(1,1), (1,2), (1,3), (1,4), (2,1), (2,3), (3,1), (3,2), (3,4), (4,1), (4,3)这些桌子。
输入:
首先第一行,输入一个测试数量t,接下来t行,每行一个n。
输出:
t行,每行对应一个解,就是Stan最少要擦几张桌子。
样例:
输入:
3
1
2
3
输出:
1
3
7
为保证正确性,你可以按照如下格式编程
int main()
{
int case;
scanf("%d",&case);
while(case--){
//你的代码
}
return 0;
}
有两组测试数据:(1)0 <n <=1000,时间:5秒.内存:32MB
(2)0 <n <=1,000,000 时间:2秒.内存:32MB
2.世界上有鬼吗?如果有,那就一定有捉鬼大师。但捉鬼大师们法力有限,他们只能消灭位于他们东南面的鬼。也就是说,如果把捉鬼大师所在位置视为原点,那么他们只能消灭第四象限的鬼怪(位于x正半轴和y负半轴上的鬼也会被消灭)。
现在给出一些鬼和坐标和一些捉鬼大师的坐标,请问有多少个鬼不会被消灭?
输入:
第一行,给出两个数字g,b对应予鬼的个数和捉鬼大师的个数。接下来的g行,每行两个整数,是每个鬼的坐标(之间有一个空各分开),在接下来得b行,每行两个整数,是每个捉鬼大师的坐标(之间有一个空各分开),不会有重复的鬼或重复的捉鬼大师出现。
输出:
无法被消灭的鬼的坐标x,y,之间用一个空格分开。注意这些坐标输出顺序必须 按照y值得绛序排列,当y相等时,则按照x的绛序排列。
样例:
输入:
3 2
0 5
1 2
2 3
1 4
-2 3
输出:
0 5
建议:
int main()
{
int g,b;
scanf("%d %d",&g,&b);
for(int i=0;i<g;i++)
//读入鬼坐标
for(int i=0;i<b;i++)
//读入捉鬼大师坐标
//你的代码
return 0;
}
有两组测试数据:(1)0 <g,b<=8000,时间:2秒,内存:32MB
(2)0 <g,b<=150000,时间:2秒,内存:32MB
环境:p4 2.2 512M gcc or g++ 64位数据请使用long long int
如有问题请在这里提问
[url=http://www.programfan.com/club/post-266202.html ]http://www.programfan.com/club/post-266202.html [/url]
最后更新于:2008-01-27 16:35:00
回复列表 (共13个回复)
板凳
nobush [专家分:390] 发布于 2008-01-24 17:15:00
[size=4]雖然達不到要求,還是跟帖,重在參與~
不過我對題目有異議 據我所知 目前的餐館最多放300張桌子。 像這樣一百萬的平方數量級的桌子,哪有地方放得下?
[/size]
[code]
/* 第一題 */
#include<stdio.h>
int main()
{
long n,i,j,a,b,tmp;
long long s;
int casa;
scanf("%d",&casa);
while(casa--)
{
scanf("%ld",&n);
s=n;
for(i=2;i<=n;i++)
for(j=2;j<i;j++)
{
a=i;b=j;
while(tmp=a%b)
{
a=b;
b=tmp;
}
if(b==1) s++;
}
s=2*s-1;
printf("%lld\n",s);
}
return 0;
}
[/code]
[code]
/* 第二題 */
#include<stdio.h>
#include<stdlib.h>
int main()
{
long g,b,i,j,tmp;
long *cg, *cb, *pg;
scanf("%ld %ld",&g,&b);
cg=(long *)malloc(2*g*sizeof(long));
cb=(long *)malloc(2*b*sizeof(long));
pg=(long *)malloc(g*sizeof(long));
for(i=0;i<g;i++)
{
pg[i]=i;
scanf("%ld %ld",&cg[2*i],&cg[2*i+1]);
}
for(i=0;i<b;i++)
{
scanf("%ld %ld",&cb[2*i],&cb[2*i+1]);
}
for(i=0;i<b;i++)
{
for(j=0;j<g;j++)
{
if(cg[pg[j]*2]<cb[2*i] || cg[2*pg[j]+1]>cb[2*i+1])
continue;
pg[j]=pg[--g];
}
if(!g) break;
}
for(i=0;i<g-1;i++)
for(j=i+1;j<g;j++)
if(cg[2*pg[i]+1]<cg[2*pg[j]+1])
{
tmp=pg[i];
pg[i]=pg[j];
pg[j]=tmp;
}
for(i=0;i<g;i++)
printf("%ld %ld\n",cg[pg[i]*2],cg[2*pg[i]+1]);
free(cg);
free(cb);
free(pg);
return 0;
}
[/code]
3 楼
maizili1987 [专家分:10] 发布于 2008-01-24 23:05:00
/*
程序名:擦桌子
程序思路:
1。建立二维数组;
2。从(1,1)开始穷举,直到所有的位置都穷尽。
作者:麦子
*/
#include "stdio.h"
#define N 1000000
main()
{
unsigned int i,j,k,t1,t2;
unsigned int m;
unsigned int n1,n2,n;
unsigned int a[N][N]={0,0};
scanf("%d",&m);
while(m--)
{
printf("\n");
scanf("%d",&n);
n1=n2=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
a[i][j]=0;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(a[i][j]==0)
{
t1=i;
t2=j;
for(k=1;((t1+1)*k<=n)&&((t2+1)*k<=n);k++)
{
a[k*(t1+1)-1][k*(t2+1)-1]=1;
n1++;
}
n2++;
}
if(n1==n*n)
{
printf("%d",n2);
break;
}
}
if(n1==n*n)
break;
}
}
printf("\n");
getchar();
getchar();
}
/*
程序名:捉鬼
程序思路:
1。先输入鬼和捉鬼大师,并且用两个数组纪录;
2。按捉鬼大师的坐标逐个杀鬼,直到所有的鬼都被捉到,捉到的置0;
3。将没捉到的抓出来?
4. 当出现(0,0)作为鬼时分开讨论。
作者:麦子
*/
#include "stdio.h"
#define N 150000
int main()
{
int g,b;
int a[N][2]={0},c[N][2]={0};
int i,j;
int temp,n=0;
int flag=0;
scanf("%d %d",&g,&b);
printf("\n");
for(i=0;i<g;i++)
{
getchar();
scanf("%d %d",&a[i][0],&a[i][1]);
}
for(i=0;i<b;i++)
{
getchar();
scanf("%d %d",&c[i][0],&c[i][1]);
}
for(i=0;i<g;i++)
{
if((a[i][0]==0)&&(a[i][1]==0))
{
for(j=0;j<b;j++)
{
if((a[i][0]<c[j][0])||(a[i][1]>c[j][1]))
{
flag=1;
}
}
4 楼
eastcowboy [专家分:25370] 发布于 2008-01-25 20:53:00
第一题:
/*****************************************************************************
原始思路:求最大公约数。
坐标为(x, y)的桌子,求x和y的最大公约数,若为1则需要擦,否则不需要擦。证明略。
时间复杂度:O(n^2 * 求最大公约数的复杂度),百万的数量级无法快速算出。
另外途径:
共n*n张桌子,本来需要擦n*n次
[以下均假设k为正证书,且坐标都小于等于n]
先考虑(k, k)的情况,可少擦k-1次
再考虑(k, 2k), (k, 3k), ..., (k, nk)
以及(2k, k), (3k, k), ..., (nk, k)
对于(k, ik),可少擦n/i+1次
对于(ik, k),可少擦n/i+1次
注意使用long long int来避免数据溢出
*****************************************************************************/
/*****************************************************************************
编程语言:C语言
测试环境:Visual Studio 2005
*****************************************************************************/
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
long long int cal(int n) {
int i;
long long int ret = ((long long int)n) * n;
ret += (1 - n);
for(i=2; i<=n; ++i) {
int count = n / i;
ret += (1-count)*2;
}
return ret;
}
int main() {
int nCase;
scanf("%d", &nCase);
while( nCase-- ) {
int n;
scanf("%d", &n);
printf("%I64ld\n", cal(n));
}
return 0;
}
5 楼
eastcowboy [专家分:25370] 发布于 2008-01-25 20:53:00
第二题:
/*****************************************************************************
原始思路:
考虑到对输出结果顺序的要求,先排序后判断
注意数量级在15万时,直接比较是不可行的,因为直接比较的时间复杂度是平方级
优化:
多处利用空间换取时间。记录鬼的位置要记录三份:
一份是输出要求的顺序,一份是x坐标顺序,一份是y坐标顺序。
其中第一份是实际的数据,后两份都是指针,
这样保证所有的数据最终都指向同一个地方。便于做标记。
对于给定的捉鬼大师,先找Y坐标相同的鬼。这样可以排除Y坐标大的鬼,做标记。
O(log(n) + 做标记的时间)
再找X坐标相同的鬼,这样可以排除X坐标小的鬼。O(log(n) + 做标记的时间)
未排除的鬼会被捉。
时间复杂度:O(n*log(g)+做标记的时间),
做标记时需要较多时间,O(n*(log(g)+g*c)) = O(n*log(g) + n*g*c),而其中c较小。
再次优化:
并非每个捉鬼大师都需要与每个鬼进行判断。所有的大师中,只有最左上方的才是有效的。
比如有三个大师(0, 0), (0, -1), (-1, 0),则其实大师(0, 0)即使不存在,也没有任何影响。
所有有效的大师组成一个阶梯状。先把大师按x坐标排序,x坐标相等的按y坐标排序。
y坐标比前一个大师大的大师才是有效的。
优化后虽然最坏情况下复杂度不变,但是对随机数据可大幅度提高性能。
小技巧:
使用C++的sort排序,可达到比C语言的qsort更快的速度
不足:
使用了set,这个地方应该还有优化余地
*****************************************************************************/
/*****************************************************************************
编程语言:C++
测试环境:Visual Studio 2005
*****************************************************************************/
#define _CRT_SECURE_NO_DEPRECATE
#include <cstdio>
#include <set>
#include <algorithm>
using namespace std;
struct Ghost {
int x;
int y;
int catched;
Ghost() : catched(0) {
}
Ghost(int x, int y) : x(x), y(y), catched(0) {
}
};
struct Catcher {
int x;
int y;
};
static bool comp_catcher_xy_less(const Catcher& a, const Catcher& b) {
if( a.x < b.x )
return true;
if( a.x == b.x && a.y < b.y )
return true;
return false;
}
static bool comp_ghost_yx_greater(const Ghost& a, const Ghost& b) {
if( a.y > b.y )
return true;
if( a.y == b.y && a.x > b.x )
return true;
return false;
}
static bool comp_ghost_x_less(Ghost* const& a, Ghost* const& b) {
return a->x < b->x;
}
static bool comp_ghost_y_less(Ghost* const& a, Ghost* const& b) {
return a->y < b->y;
}
static int optimizeCatcherList(Catcher* pCatcherList, int nCatcher) {
sort(pCatcherList, pCatcherList+nCatcher, comp_catcher_xy_less);
int p = 1;
for(int i=1; i<nCatcher; ++i) {
if( pCatcherList[i].y > pCatcherList[i-1].y )
pCatcherList[p++] = pCatcherList[i];
}
return p;
}
int main() {
int nGhost, nCatcher;
scanf("%d%d", &nGhost, &nCatcher);
Ghost* pGhostList = new Ghost[nGhost];
Catcher* pCatcherList = new Catcher[nCatcher];
for(int i=0; i<nGhost; ++i)
scanf("%d%d", &(pGhostList[i].x), &(pGhostList[i].y));
for(int i=0; i<nCatcher; ++i)
scanf("%d%d", &(pCatcherList[i].x), &(pCatcherList[i].y));
// 排除无影响的大师
nCatcher = optimizeCatcherList(pCatcherList, nCatcher);
// 将鬼按输出要求排序
sort(pGhostList, pGhostList+nGhost, comp_ghost_yx_greater);
// 复制鬼数据指针,按x和y分别排序
Ghost** pGhostPtrListX = new Ghost*[nGhost];
Ghost** pGhostPtrListY = new Ghost*[nGhost];
for(int i=0; i<nGhost; ++i) {
pGhostPtrListX[i] = &(pGhostList[i]);
pGhostPtrListY[i] = &(pGhostList[i]);
}
sort(pGhostPtrListX, pGhostPtrListX+nGhost, comp_ghost_x_less);
sort(pGhostPtrListY, pGhostPtrListY+nGhost, comp_ghost_y_less);
// 实际处理
for(int i=0; i<nCatcher; ++i) {
Ghost dummyGhost = Ghost(pCatcherList[i].x, pCatcherList[i].y);
set<Ghost*> ghostSet;
// 找出所有x值比大师更大的(含相等),放入集合
int iX = lower_bound(pGhostPtrListX, pGhostPtrListX+nGhost,
&dummyGhost, comp_ghost_x_less) - pGhostPtrListX;
for(i=iX; i<nGhost; ++i)
if( !pGhostPtrListX[i]->catched )
ghostSet.insert(pGhostPtrListX[i]);
// 找出所有y值比大师更小的(含相等),若在集合中有对应元素,则标记为捉住
int iY = lower_bound(pGhostPtrListY, pGhostPtrListY+nGhost,
&dummyGhost, comp_ghost_y_less) - pGhostPtrListY;
for(i=0; i<=iY; ++i)
if( !pGhostPtrListY[i]->catched )
if( ghostSet.find(pGhostPtrListY[i]) != ghostSet.end() )
pGhostPtrListY[i]->catched = 1;
}
// 输出
for(int i=0; i<nGhost; ++i)
if( !pGhostList[i].catched )
printf("%d %d\n", pGhostList[i].x, pGhostList[i].y);
delete[] pGhostList;
delete[] pGhostPtrListX;
delete[] pGhostPtrListY;
delete[] pCatcherList;
return 0;
}
6 楼
dongch007 [专家分:20] 发布于 2008-01-26 16:17:00
#include "stdio.h"
int CD(int x)//第x行第x列,不需要擦的个数
{
int n,m,k=0;
for(n=2; n<x; n++)
{
for(m=2;m<=n;m++)
{
if(n%m==0 && x%m==0)
{
k++;
break;
}
}
}
k=2*k+1;
return k;
}
int main()
{
int t;
int n,m,k;
scanf("%d",&t);
while(t--)
{
m=0;
k=0;
scanf("%d",&n);
if(n==1)
m=1;
else
{
for(int i=2;i<=n;i++)
{
k+=CD(i);
}
m=n*n-k;
}
printf("%d\n",m);
}
return 0;
}
7 楼
wwc0210 [专家分:0] 发布于 2008-01-26 23:18:00
1.
#include <conio.h> /* 此头函数请不要删除 */
#include<stdio.h>
main()
{int n,i,j,k,s;
s=0;
scanf("%d",&n);
for(i=2;i<=n;i++)
{for(j=2;j<=n;j++)
{for(k=2;k<=n;k++)
{if(i/k>0&&i/k<n&&i%k==0&&j/k>0&&j/k<n&&j%k==0)
{s++;
break;}}}}
s=n*n-s;
printf("%d",s);
getch(); /* 此语句请不要删除*/
}
2.#include <conio.h> /* 此头函数请不要删除 */
#include<stdio.h>
main()
{int g,b,i,j,m,n,x1[10],x2[10],y1[10],y2[10];
m=0;
n=0;
scanf("%d &d",&g,&b);
for(i=0;i<g;i++)
scanf("%d &d",&x1[i],&y1[i]);
for(j=0;j<b;j++)
scanf("%d &d",&x2[j],&y2[j]);
for(j=0;j<b;j++)
for(i=0;i<g;i++)
{if(x2[j]>x1[i]&&y2[j]<y1[i])
{if(m!=x1[i]&&n!=y1[i])
{m=x1[i];
n=y1[i];
printf("%d %d",m,n);}}}
getch(); /* 此语句请不要删除*/
}
8 楼
shekaka [专家分:1630] 发布于 2008-01-27 10:39:00
[code=c]
//小孩擦桌子
#include <iostream>
using namespace std;
const int MAX = 2000000;
void track(int);
int main() {
int ipn = 0;
cout << "put the test number: ";
cin >> ipn;
if( ipn > MAX )
{
cout << "Too large number!" << endl;
return -1;
}
else cout << "no. " <<"test number" << endl;
track(ipn);
return 0;
}
void track(int ipn) {
long long int count = 0;
for (int i = 0; i < ipn; ++i) {
if ( (i & 0x00000001 ) == 1)
count += i - ( (i - 1 ) >> 1 );
else
count += i;
cout << i + 1 << " " << count + count + 1 << endl;
}
}
[/code]
9 楼
shekaka [专家分:1630] 发布于 2008-01-27 10:39:00
[code=c]
//鬼大师捉鬼
#include <iostream>
using namespace std;
typedef struct LocalType {
int x;
int y;
}LocalType;
int partition( LocalType*, int, int, char );
void quickSort( LocalType*, int, int, char );
int sort( LocalType*, int ); //先y升序,再x升序
int main() {
int g, b, count_g, count_b, count = 0;
cout << "输入:" << endl;
cin >> g;
cin >> b;
LocalType *local_g = new LocalType[g];
LocalType *local_b = new LocalType[b];
int i = 0;
for ( i = 0; i < g; ++i ) {
cin >> local_g[i].x;
cin >> local_g[i].y;
}
for ( i = 0; i < b; ++i ) {
cin >> local_b[i].x;
cin >> local_b[i].y;
}
count_g = sort ( local_g, g );
count_b = sort ( local_b, b );
LocalType *local_t = new LocalType[count_b];
for ( i = b - 1; i >= 0; --i ) { //筛选有用的道士
while ( i > 0 && local_b[i].y == local_b[ i - 1 ].y ) --i;
if ( count == 0 || local_b[i].x < local_t[ count -1 ].x ) {
local_t[count] = local_b[i];
++count;
}//if
}//for
delete [] local_b;
cout << "输出:" << endl;
int j = 0;
for ( i = g - 1; i >= 0; --i ) { //输出鬼,y降序,再x降序
while ( j < count && local_g[i].y <= local_t[j].y ) ++j;
if ( local_g[i].y > local_t[0].y || local_g[i].x < local_t[ j - 1 ].x ) {
cout << local_g[i].x << " " << local_g[i].y << endl;
j = 0;
}//if
}//for
delete [] local_g;
delete [] local_t;
return 0;
}
int partition( LocalType *L, int low, int high, char a ) {
int pivot = 0;
LocalType t = L[low];
if ( a == 'x' ) {
pivot = L[low].x;
while ( low < high ) {
while ( low < high && L[high].x >= pivot ) --high;
L[low] = L[high];
while ( low < high && L[low].x <= pivot ) ++low;
L[high] = L[low];
}
}
else {
pivot = L[low].y;
while ( low < high ) {
while ( low < high && L[high].y >= pivot ) --high;
L[low] = L[high];
while ( low < high && L[low].y <= pivot ) ++low;
L[high] = L[low];
}
}
L[low] = t;
return low;
}//partition
void quickSort( LocalType *L, int low, int high, char a ) {
int pivot = 0;
if ( low < high ) {
pivot = partition( L, low, high, a );
quickSort( L, low, pivot - 1, a );
quickSort( L, pivot + 1, high, a );
}
}//quickSort
int sort( LocalType *L, int size ) {
int count = 0;
int low, high;
quickSort( L, 0, size - 1, 'y' );
for ( int i = 0; i < size; ++i ) {
low = i;
while ( i + 1 < size && L[i].y == L[ i + 1 ].y ) ++i;
high = i;
quickSort ( L, low, high, 'x' );
count++;
}
return count;
}
[/code]
10 楼
yxs0001 [专家分:9560] 发布于 2008-01-27 16:26:00
#include <iostream>
using namespace std;
class CNum{
private:
int n;
int Factors;
int Factor[7];//[0]为素因子个数,其后为素因子列表
public:
int Euler();
int GetN(){return n;}
bool IsPrime(){return Factors == 0;}
void AddPrime(int p){ Factors ++; Factor[Factors-1] = p;}
void Set(int nn){ n = nn; Factors = 0;}
CNum(int nn){ Set(nn);}
CNum(){}
};
int CNum::Euler()
{
int tmp = 1;
int temp = 1;
for(int i=0;i<Factors;i++){
tmp *= Factor[i];
temp *= Factor[i] - 1;
}
return n/tmp*temp;
}
class CNode{
private:
int num;
int tmp;
CNode *N;
public:
CNode(){ Set(0,0,NULL);}
CNode(int n,int t){ Set(n,t,NULL);}
void Set(int n,int t,CNode *p){ num = n;tmp = t; N = p;}
void SetTmp(int t){ tmp = t;}
int GetTmp(){return tmp;}
void SetNext(CNode *p){ N = p;}
CNode* GetNext(){return N;}
int GetNum(){return num;}
void MoveTmp(int t){tmp -= t;}
~CNode(){ if (N) delete N;}
};
//返回i,j (i<=n,j<=n) 互质的对数 即本题结果
long long tables(int n)
{
long long result = 1; //结果
long long tmp = 0; //2..n的欧拉函数总和
int start = 2; //第一个数
const int LEN = 25000; //数组长
CNum cn[LEN]; //数组
int cnl = 0; //数组有效长度
CNode *Head = new CNode; //素数链表
CNode *Tail = Head;
while(start<=n){
//确定长度
cnl = (LEN < (n-start+1)) ? LEN : (n-start+1);
//初始化数组
for(int i=0;i<cnl;i++){
cn[i].Set(start + i);
}
//用素数列表中的数字筛选数组
CNode *p = Head;
while(p = p->GetNext()){
int i;
for(i=p->GetTmp();i<cnl;i+=p->GetNum()){
cn[i].AddPrime(p->GetNum());
}
p->SetTmp(i);
Tail = p;
}
//将数组中的素数加入素数列表 并筛选数组
for(int i=0;i<cnl;i++){
if(cn[i].IsPrime()){
p = new CNode(cn[i].GetN(),i);
Tail->SetNext(p);
Tail = p;
int j;
for(j=p->GetTmp();j<cnl;j += p->GetNum()){
cn[j].AddPrime(p->GetNum());
}
p->SetTmp(j);
}
}
//计算数组各项的欧拉函数 并 求和
for(int i=0;i<cnl;i++){
tmp += cn[i].Euler();
}
//对素数链表偏移
p = Head;
while(p = p->GetNext()){
p->MoveTmp(cnl);
}
start += cnl;
}
result += 2*tmp;
return result;
}
int main()
{
int lines;
int n;
clock_t start,finish;
double duration;
cin>>lines;
while(lines --){
cin>>n;
cout<<tables(n)<<endl;
}
cin>>lines;
return 0;
}
如果溢出,楼主帮忙修改一下 const int LEN = 25000; //数组长
LEN越大效率越高,
我来回复