sihai的博客

life is always beautiful like sunshine

蓝桥杯练习系统习题-历年真题解析2(完整版)

文章推荐

蓝桥杯练习系统习题-历年真题解析2

题目搜索方式:Ctrl+F—-> 输入题目名称—>定位到解答.

入门训练(详见 算法-蓝桥杯习题(1-1))

基础练习(详见 算法-蓝桥杯习题(2-1))

基础练习(详见 算法-蓝桥杯习题(2-2))

算法训练(详见 算法-蓝桥杯习题(3-1))

算法训练(详见 算法-蓝桥杯习题(3-2))

算法训练(详见 算法-蓝桥杯习题(3-3))

算法训练(详见 算法-蓝桥杯习题(3-4))

算法训练(详见 算法-蓝桥杯习题(3-5))

算法训练(详见 算法-蓝桥杯习题(3-6))

算法提高(详见 算法-蓝桥杯习题(4-1))

算法提高(详见 算法-蓝桥杯习题(4-2))

历届试题(详见 算法-蓝桥杯习题(5-1))

历届试题(详见 算法-蓝桥杯习题(5-2))

历届试题 车轮轴迹

问题描述
  栋栋每天骑自行车回家需要经过一条狭长的林荫道。道路由于年久失修,变得非常不平整。虽然栋栋每次都很颠簸,但他仍把骑车经过林荫道当成一种乐趣。
  由于颠簸,栋栋骑车回家的路径是一条上下起伏的曲线,栋栋想知道,他回家的这条曲线的长度究竟是多长呢?更准确的,栋栋想知道从林荫道的起点到林荫道的终点,他的车前轮的轴(圆心)经过的路径的长度。
  栋栋对路面进行了测量。他把道路简化成一条条长短不等的直线段,这些直线段首尾相连,且位于同一平面内。并在该平面内建立了一个直角坐标系,把所有线段的端点坐标都计算好。
  假设栋栋的自行车在行进的过程中前轮一直是贴着路面前进的。

图片请百度

  上图给出了一个简单的路面的例子,其中蓝色实线为路面,红色虚线为车轮轴经过的路径。在这个例子中,栋栋的前轮轴从A点出发,水平走到B点,然后绕着地面的F点到C点(绕出一个圆弧),再沿直线下坡到D点,最后水平走到E点,在这个图中地面的坐标依次为:(0, 0), (2, 0), (4, -1), (6, -1),前轮半径为1.50,前轮轴前进的距离依次为:
  AB=2.0000;弧长BC=0.6955;CD=1.8820;DE=1.6459。
  总长度为6.2233。

  下图给出了一个较为复杂的路面的例子,在这个例子中,车轮在第一个下坡还没下完时(D点)就开始上坡了,之后在坡的顶点要从E绕一个较大的圆弧到F点。这个图中前轮的半径为1,每一段的长度依次为:
  AB=3.0000;弧长BC=0.9828;CD=1.1913;DE=2.6848;弧长EF=2.6224; FG=2.4415;GH=2.2792。
  总长度为15.2021。

图片请百度

  现在给出了车轮的半径和路面的描述,请求出车轮轴轨迹的总长度。
输入格式
  输入的第一行包含一个整数n和一个实数r,用一个空格分隔,表示描述路面的坐标点数和车轮的半径。
  接下来n行,每个包含两个实数,其中第i行的两个实数x[i], y[i]表示描述路面的第i个点的坐标。
  路面定义为所有路面坐标点顺次连接起来的折线。给定的路面的一定满足以下性质:

  *第一个坐标点一定是(0, 0);
  *第一个点和第二个点的纵坐标相同;
  *倒数第一个点和倒数第二个点的纵坐标相同;
  *第一个点和第二个点的距离不少于车轮半径;
  *倒数第一个点和倒数第二个点的的距离不少于车轮半径;
  *后一个坐标点的横坐标大于前一个坐标点的横坐标,即对于所有的i,x[i+1]>x[i]。
输出格式
  输出一个实数,四舍五入保留两个小数,表示车轮轴经过的总长度。
  你的结果必须和参考答案一模一样才能得分。数据保证答案精确值的小数点后第三位不是4或5。
样例输入
4 1.50
0.00 0.00
2.00 0.00
4.00 -1.00
6.00 -1.00
样例输出
6.22
样例说明
  这个样例对应第一个图。
样例输入
6 1.00
0.00 0.00
3.00 0.00
5.00 -3.00
6.00 2.00
7.00 -1.00
10.00 -1.00
样例输出
15.20
样例说明
  这个样例对应第二个图
数据规模和约定
  对于20%的数据,n=4;
  对于40%的数据,n≤10;
  对于100%的数据,4≤n≤100,0.5≤r≤20.0,x[i] ≤2000.0,-2000.0≤y[i] ≤2000.0。

 #include <iostream>  
 #include <cstdlib>  
 #include <cstdio>  
 #include <cstring>  
 #include <vector>  
 #include <cmath>  
 #include <algorithm>  
 using namespace std;  
 const int MAXN = 10000;  
 const double PI = atan(1.0) * 4;  
 const double EPS = 1e-10;  
 class Point {  
 public:  
     double x, y;  
     Point() {}  
     Point(double x, double y) : x(x), y(y) {}  
     Point operator - (const Point &r) const { return Point(x-r.x, y-r.y); }  
     Point operator + (const Point &r) const { return Point(x+r.x, y+r.y); }  
     Point &operator += (const Point &r) { x += r.x; y += r.y; return *this; }  
     Point &operator *= (double m) { x *= m; y *= m; return *this; }  
     Point pOfRotate(double angle) const {  
         double cosA = cos(angle);  
         double sinA = sin(angle);  
         return Point(cosA*x-sinA*y, sinA*x+cosA*y);  
     }  
     Point pOfRotate90() const { return Point(-y, x); }  
     double length() const { return sqrt(x*x+y*y); }  
     Point pOfNormal() const {  
         double len = length();  
         return Point(x/len, y/len);  
     }  
     double angle() const { return atan2(y, x); }  
 };  
 ostream & operator <<(ostream &os, const Point &v)  
 {  
     os << "(" << v.x << "," << v.y << ")";  
     return os;  
 }  
 class Segment;  
 class Circle;  
 class Seg {  
 public:  
     virtual double getLeft() const = 0;  
     virtual double getRight() const = 0;  
     virtual double getY(double x) const = 0;  
     virtual double getLength(double x1, double x2) const = 0;  
     virtual void intersect(Seg *r) const = 0;  
     virtual void intersect(const Segment &v) const = 0;  
     virtual void intersect(const Circle &v) const = 0;  
     bool contains(double x) const { return x>=getLeft() && x<=getRight(); }  
     virtual void acceptPrint(ostream &os) const = 0;  
 };  
 ostream & operator <<(ostream &os, const Seg &v)  
 {  
     v.acceptPrint(os);  
     return os;  
 }  
 Point intersectRet[4];  
 int tIntersectRet;  
 class Segment : public Seg {  
 public:  
     Point a, b;  
     Segment &moveLeft(double dis)  
     {  
         Point tmp = ((b-a).pOfRotate90().pOfNormal() *= dis);  
         a += tmp;  
         b += tmp;  
         return *this;  
     }  
     virtual double getLeft() const { return a.x; }  
     virtual double getRight() const { return b.x; }  
     virtual double getY(double x) const {  
         return (x-a.x)*(b.y-a.y)/(b.x-a.x)+a.y;  
     }  
     virtual double getLength(double x1, double x2) const {  
         return (x2-x1) * (b-a).length() / (b.x-a.x);  
     }  
     virtual void intersect(Seg *r) const {  
         r->intersect(*this);  
     }  
     virtual void intersect(const Segment &v) const {  
         tIntersectRet = 0;  
         double ang = (b-a).angle();  
         Point c = (v.a-a).pOfRotate(-ang);  
         Point d = (v.b-a).pOfRotate(-ang);  
         // Bug  
         //double di = b.length();  
         double di = (b-a).length();  
         if (!((c.y>0&&d.y<0) || (c.y<0&&d.y>0)))  
             return ;  
         double x = (d.x-c.x) * (-c.y) / (d.y-c.y) + c.x;  
         if (x<0 || x>di)  
             return ;  
         Point ret = Point(x,0).pOfRotate(ang)+a;  
         intersectRet[tIntersectRet++] = ret;  
     }  
     virtual void intersect(const Circle &v) const;  
     virtual void acceptPrint(ostream &os) const {  
         os << a << "-" << b;  
     }  
 };  
 class Circle : public Seg {  
 public:  
     Point c;  
     double r;  
     virtual double getLeft() const { return c.x - r; }  
     virtual double getRight() const { return c.x + r; }  
     virtual double getY(double x) const {  
         double y2 = r * r - (c.x - x) * (c.x - x);  
         if (y2<0) y2 = 0;  
         return c.y + sqrt(y2);  
     }  
     virtual double getLength(double x1, double x2) const {  
         x1 -= c.x; x2 -= c.x;  
         double a1 = Point(x1, sqrt(abs(r*r-x1*x1))).angle(), a2 = Point(x2, sqrt(abs(r*r-x2*x2))).angle();  
         return (a1-a2) * r;  
     }  
     virtual void intersect(Seg *r) const {  
         r->intersect(*this);  
     }  
     virtual void intersect(const Segment &v) const {  
         tIntersectRet = 0;  
         Point a = v.a - c;  
         Point b = v.b - c;  
         double ang = (b-a).angle();  
         Point nA = a.pOfRotate(-ang);  
         Point nB = b.pOfRotate(-ang);  
         double y = nA.y;  
         if (y>r || y<-r)  
             return ;  
         double x = sqrt(r*r - y*y);  
         if (x>=nA.x && x<=nB.x)  
             intersectRet[tIntersectRet++] = Point(x, y).pOfRotate(ang) + c;  
         if (-x>=nA.x && -x<=nB.x)  
             intersectRet[tIntersectRet++] = Point(-x, y).pOfRotate(ang) + c;  
     }  
     virtual void intersect(const Circle &v) const {  
         tIntersectRet = 0;  
         Point p = v.c - c;  
         double d = p.length();  
         if (d > r + v.r || d==0)  
             return ;  
         double x = (r*r - v.r*v.r + d*d) / (2*d);  
         if (x <= r)  
         {  
             double y = sqrt(abs(r*r - x*x));  
             double ang = p.angle();  
             intersectRet[tIntersectRet++] = Point(x,y).pOfRotate(ang) + c;  
             intersectRet[tIntersectRet++] = Point(x,-y).pOfRotate(ang) + c;  
         }  
     }  
     virtual void acceptPrint(ostream &os) const {  
         os << c << "," << r;  
     }  
 };  
 void Segment::intersect(const Circle &v) const {  
     v.intersect(*this);  
 }  
 int n;  
 Point inps[MAXN];  
 vector<Seg *> segs;  
 vector<double> spes;  
 double radius = 1;  
 void input()  
 {  
     scanf("%d%lf", &n, &radius);  
     for (int i = 0; i < n; ++i)  
     {  
         double x, y;  
         scanf("%lf%lf", &x, &y);  
         inps[i] = Point(x, y);  
     }  
 }  
 void process()  
 {  
     segs.clear();  
     spes.clear();  
     for (int i = 1; i + 1 < n; ++i)  
     {  
         Circle *tmp = new Circle;  
         tmp->c = inps[i];  
         tmp->r = radius;  
         segs.push_back(tmp);  
     }  
     for (int i = 0; i + 1 < n; ++i)  
     {  
         Segment *tmp = new Segment;  
         tmp->a = inps[i];  
         tmp->b = inps[i+1];  
         tmp->moveLeft(radius);  
         segs.push_back(tmp);  
     }  
     for (int i = 0; i < (int)segs.size(); ++i)  
     {  
         spes.push_back(segs[i]->getLeft());  
         spes.push_back(segs[i]->getRight());  
     }  
     for (int i = 0; i < (int)segs.size(); ++i)  
     {  
         for (int j = i+1; j < (int)segs.size(); ++j)  
         {  
             segs[i]->intersect(segs[j]);  
             if (tIntersectRet > 0)  
             {  
                 for (int id = 0; id < tIntersectRet; ++id)  
                 {  
                     //cout << *segs[i] << " " << *segs[j] << " : " << intersectRet[id] << endl;  
                     spes.push_back(intersectRet[id].x);  
                 }  
             }  
         }  
     }  
     sort(spes.begin(), spes.end());  
     double pre = spes[0];  
     const double NONE = 1e30;  
     double preEnd = NONE;  
     double totalLen = 0;  
     for (int i = 1; i < (int)spes.size(); ++i)  
     {  
         if (spes[i]-pre < EPS)  
             continue;  
         double cur = (pre+spes[i]) / 2;  
         //cout << "Processing " << cur << "  from " << pre << " to " << spes[i] << endl;  
         if (cur>=inps[0].x && cur<=inps[n-1].x)  
         {  
             double MY = -NONE;  
             int who;  
             for (int j = 0; j < (int)segs.size(); ++j)  
             {  
                 if (!segs[j]->contains(cur))  
                     continue;  
                 double y = segs[j]->getY(cur);  
                 if (y > MY)  
                 {  
                     MY = y;  
                     who = j;  
                 }  
             }  
             if (preEnd != NONE)  
             {  
                 double LY = segs[who]->getY(pre);  
                 //cout << "Drop info " << *segs[who] << " " << "[" << pre << "]" << endl;  
                 totalLen += abs(preEnd-LY);  
                 //cout << "Pre drop = " << abs(preEnd-LY) << "  from " << preEnd << " to " << LY << endl;  
             }  
             double len = segs[who]->getLength(pre, spes[i]);  
             if (len < 0)  
                 printf("Error!\n");  
             //cout << "Curlen = " << len << " from " << pre << " to " << spes[i] << endl;  
             totalLen += len;  
             preEnd = segs[who]->getY(spes[i]);  
         }  
         pre = spes[i];  
     }  
     printf("%0.2lf\n", totalLen);  
     for (int i = 0; i < (int)segs.size(); ++i)  
         delete segs[i];  
     segs.clear();  
 }  
 int main()  
 {  
     input();  
     process();  
     return 0;  
 }  

历届试题 九宫重排

问题描述
  如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。

图为2个9宫格,第一个为123,456,78空格。第二个为123,空格46,758。

  我们把第一个图的局面记为:12345678.
  把第二个图的局面记为:123.46758
  显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
  本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入格式
  输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
  输出最少的步数,如果不存在方案,则输出-1。
样例输入


  1. 123.46758
    样例输出
    3
    样例输入

    1. 样例输出
      22
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<string.h>  
 typedef struct _Node  
 {  
     char tab[3][3];  
     int x,y;  
     int no;  
 }Node,*pNode;  
 int vx[4]={-1,1,0,0};  
 int vy[4]={0,0,-1,1};  
 Node res[400000];  
 int front=0,rear=0;  
 int vis[4000000],fact[9];   
 void input(pNode start);  
 void bfs(pNode start,pNode end);  
 void init_lookup_table();  
 int try_to_insert(int s);  
 int main()  
 {  
     Node start,end;  
     input(&start);  
     input(&end);  
     bfs(&start,&end);  
     printf("-1\n");  
     return 0;   
 }  
 void input(pNode start)  
 {  
     int i,j;  
     for(i=0;i<3;i++)  
     {  
         for(j=0;j<3;j++)  
         {  
             scanf("%c",&( (start->tab)[i][j] ));  
             if((start->tab)[i][j]=='.')  
             {  
                 start->x = i;  
                 start->y = j;  
             }  
         }  
     }  
     start->no = 0;  
     getchar();  
 }  
 void bfs(pNode start,pNode end)  
 {  
     int i,j;  
     char ch;  
     pNode tmp;  
     init_lookup_table();  
     memcpy(&res[rear],start,sizeof(res[rear]));  
     try_to_insert(rear);   
     rear++;  
     while(front!=rear)  
     {  
         //printf("%d  ",rear);  
         tmp = &res[front];  
         if(memcmp(tmp->tab,end->tab,sizeof(end->tab))==0)  
         {  
             printf("%d\n",tmp->no);  
             exit(0);  
         }  
         int no = tmp->no;  
         for(i=0;i<4;i++)  
         {  
             int xx = tmp->x+vx[i];  
             int yy = tmp->y+vy[i];  
             if(xx>=0 && xx<3 && yy>=0 && yy<3)  
             {  
                 pNode p = &res[rear];  
                 memcpy(p,tmp,sizeof(res[front]));  
                 p->tab[tmp->x][tmp->y] = p->tab[xx][yy];  
                 p->tab[xx][yy] = tmp->tab[tmp->x][tmp->y];  
                 p->no = no+1;  
                 p->x = xx;  
                 p->y = yy;  
                 if(try_to_insert(rear))  
                 {  
                     rear++;  
                 }  
             }  
         }  
         front++;  
         //printf("%d  ",rear);  
     }  
 }  
 void init_lookup_table()  
 {  
     int i;  
     fact[0] = 1;  
     for(i=1;i<9;i++)  
     {  
         fact[i] = fact[i-1]*i;  
     }  
 }  
 int try_to_insert(int s)  
 {  
     int i,j;  
     int code = 0;  
     for(i=0;i<9;i++)  
     {  
         int cnt = 0;  
         for(j=i+1;j<9;j++)  
         {  
             if(res[s].tab[j/3][j%3] < res[s].tab[i/3][i%3])  
             {  
                 cnt++;  
             }  
             code += fact[8-i]*cnt;  
         }  
     }  
     if(vis[code])  
     {  
         return 0;  
     }  
     return vis[code] = 1;  
 }  

历届试题 公式求值

问题描述
  输入n, m, k,输出下面公式的值。

图片请百度

  其中C_n^m是组合数,表示在n个人的集合中选出m个人组成一个集合的方案数。组合数的计算公式如下。

图片请百度

输入格式
  输入的第一行包含一个整数n;第二行包含一个整数m,第三行包含一个整数k。
输出格式
  计算上面公式的值,由于答案非常大,请输出这个值除以999101的余数。
样例输入
3
1
3
样例输出
162
样例输入
20
10
10
样例输出
359316
数据规模和约定
  对于10%的数据,n≤10,k≤3;
  对于20%的数据,n≤20,k≤3;
  对于30%的数据,n≤1000,k≤5;
  对于40%的数据,n≤10^7,k≤10;
  对于60%的数据,n≤10^15,k ≤100;
  对于70%的数据,n≤10^100,k≤200;
  对于80%的数据,n≤10^500,k ≤500;
  对于100%的数据,n在十进制下不超过1000位,即1≤n<10^1000,1≤k≤1000,同时0≤m≤n,k≤n。
提示
  999101是一个质数;
  当n位数比较多时,绝大多数情况下答案都是0,但评测的时候会选取一些答案不是0的数据;

历届试题 回文数字

问题描述
  观察数字:12321,123321 都有一个共同的特征,无论从左到右读还是从右向左读,都是相同的。这样的数字叫做:回文数字。

  本题要求你找到一些5位或6位的十进制数字。满足如下要求:
  该数字的各个数位之和等于输入的整数。
输入格式
  一个正整数 n (10<n<100), 表示要求满足的数位和。
输出格式
  若干行,每行包含一个满足要求的5位或6位整数。
  数字按从小到大的顺序排列。
  如果没有满足条件的,输出:-1
样例输入
44
样例输出
99899
499994
589985
598895
679976
688886
697796
769967
778877
787787
796697
859958
868868
877778
886688
895598
949949
958859
967769
976679
985589
994499
样例输入
60
样例输出
-1

 #include<stdio.h>  
 int main()  
 {  
     int a,b,c;  
     int n;  
     int flag=-1;  
     scanf("%d",&n);  
     for(a=1;a<10;a++)  
     {  
         for(b=0;b<10;b++)  
         {  
             for(c=0;c<10;c++)  
             {  
                 if(a+b+c+b+a==n)  
                 {  
                     flag=1;  
                     printf("%d%d%d%d%d\n",a,b,c,b,a);  
                 }  
             }  
         }  
     }  
     for(a=1;a<10;a++)  
     {  
         for(b=0;b<10;b++)  
         {  
             for(c=0;c<10;c++)  
             {  
                 if(a+b+c+c+b+a==n)  
                 {  
                     printf("%d%d%d%d%d%d\n",a,b,c,c,b,a);  
                     flag=1;  
                 }  
             }  
         }  
     }  
     if(flag==-1)  
         printf("%d\n",flag);  
     return 0;  
 }  

历届试题 国王的烦恼

问题描述
  C国由n个小岛组成,为了方便小岛之间联络,C国在小岛间建立了m座大桥,每座大桥连接两座小岛。两个小岛间可能存在多座桥连接。然而,由于海水冲刷,有一些大桥面临着不能使用的危险。

  如果两个小岛间的所有大桥都不能使用,则这两座小岛就不能直接到达了。然而,只要这两座小岛的居民能通过其他的桥或者其他的小岛互相到达,他们就会安然无事。但是,如果前一天两个小岛之间还有方法可以到达,后一天却不能到达了,居民们就会一起抗议。

  现在C国的国王已经知道了每座桥能使用的天数,超过这个天数就不能使用了。现在他想知道居民们会有多少天进行抗议。
输入格式
  输入的第一行包含两个整数n, m,分别表示小岛的个数和桥的数量。
  接下来m行,每行三个整数a, b, t,分别表示该座桥连接a号和b号两个小岛,能使用t天。小岛的编号从1开始递增。
输出格式
  输出一个整数,表示居民们会抗议的天数。
样例输入
4 4
1 2 2
1 3 2
2 3 1
3 4 3
样例输出
2
样例说明
  第一天后2和3之间的桥不能使用,不影响。
  第二天后1和2之间,以及1和3之间的桥不能使用,居民们会抗议。
  第三天后3和4之间的桥不能使用,居民们会抗议。
数据规模和约定
  对于30%的数据,1<=n<=20,1<=m<=100;
  对于50%的数据,1<=n<=500,1<=m<=10000;
  对于100%的数据,1<=n<=10000,1<=m<=100000,1<=a, b<=n, 1<=t<=100000。

 #include<stdio.h>  
 #include<malloc.h>  
 int a[100001],b[100001],c[100001],d[10001];  
 struct tubiao  
 {  
     int n;  
     struct tubiao *next;  
 }tu[10001];  
 void add(int u,int v)  
 {  
     struct tubiao *p=(struct tubiao*) malloc(sizeof(struct tubiao));  
     p->n=v;  
     p->next=NULL;  
     struct tubiao *q=&tu[u];  
     while(q->next)  
        {  q=q->next;  
        }  
     q->next=p;  
 }  
 void paixu(int first,int last)  
 {  if(first<last)  
      {  
           int i=first,j=last,ka=a[first],kb=b[first],kc=c[first];  
           while(i<j)  
           {  
               while(i<j&&kc<=c[j])  
                   j--;  
               a[i]=a[j];b[i]=b[j];c[i]=c[j];  
               while(i<j&&kc>=c[i])  
                   i++;  
              a[j]=a[i];b[j]=b[i];c[j]=c[i];  
          }  
          a[i]=ka;b[i]=kb;c[i]=kc;  
          paixu(first,i-1);  
          paixu(i+1,last);  
      }  
 }  
 int f1(int i)  
 {  
     if(d[i]==i)  
       return i;  
     int u=f1(d[i]);  
     d[i]=u;  
     return d[i];  
 }  
 int main()  
 {  
     int n,m,i1,u,v,t,i2;  
     scanf("%d%d",&n,&m);  
     for(i1=0;i1<m;i1++)  
     {   scanf("%d%d%d",&u,&v,&t);  
         a[i1]=u;b[i1]=v;c[i1]=t;  
         add(u,v);  
         add(v,u);  
     }  
     paixu(0,m-1);  
     int  total=0,tianshu=0;  
  for(i1=1;i1<=n;i1++)  
     d[i1]=i1;  
  for(i1=m-1;i1>=0;i1--)  
  {     int ko=f1(a[i1]);  
        int ok=f1(b[i1]);  
       if(ko==ok)  
           {  
              continue;      
           }  
       else   
          {  
              d[ko]=b[i1];  
              if(tianshu!=c[i1])  
                 {  
                      total++;  
                      tianshu=c[i1];  
                    }  
          }  
  }  
   printf("%d\n",total);  
     return 0;  
 }  

历届试题 数字游戏

问题描述
  栋栋正在和同学们玩一个数字游戏。

  游戏的规则是这样的:栋栋和同学们一共n个人围坐在一圈。栋栋首先说出数字1。接下来,坐在栋栋左手边的同学要说下一个数字2。再下面的一个同学要从上一个同学说的数字往下数两个数说出来,也就是说4。下一个同学要往下数三个数,说7。依次类推。

  为了使数字不至于太大,栋栋和同学们约定,当在心中数到 k-1 时,下一个数字从0开始数。例如,当k=13时,栋栋和同学们报出的前几个数依次为:
  1, 2, 4, 7, 11, 3, 9, 3, 11, 7。

  游戏进行了一会儿,栋栋想知道,到目前为止,他所有说出的数字的总和是多少。
输入格式
  输入的第一行包含三个整数 n,k,T,其中 n 和 k 的意义如上面所述,T 表示到目前为止栋栋一共说出的数字个数。
输出格式
  输出一行,包含一个整数,表示栋栋说出所有数的和。
样例输入
3 13 3
样例输出
17
样例说明
  栋栋说出的数依次为1, 7, 9,和为17。
数据规模和约定
  1 < n,k,T < 1,000,000;

 #include <stdio.h>  
 #include <windows.h>3   
 int s[1000000];  
 // 3  13  9   
 //  1 2 4 7 11 3 9 3 11 7 4 2 1    1 2 4 7 11 3 9 3 11 7 4 2 1   
 int main()  
 {  
 long long n,k,t,i,j=1,g=1,z,sum=0;  
 scanf("%I64d%I64d%I64d",&n,&k,&t);  
 if(k%2==0) z=k*2;  
 else z=k;  
 s[0]=1;  
 do    //开始制表   
 {  
 j+=g;  
 if(j>=k) j%=k;   
 s[g]=j;  
 g++;       
 }                           
 while(g<=z) ;   
 k=0;        
 for(i=0;i<t;i++)  
 {  
  sum+=s[k];  
  k+=n;  
  if(k>g-1) k-=g-1;               
 }                   
 printf("%I64d",sum);  
 system("pause");  
  return 0;     
 }  

历届试题 邮局

问题描述
  C村住着n户村民,由于交通闭塞,C村的村民只能通过信件与外界交流。为了方便村民们发信,C村打算在C村建设k个邮局,这样每户村民可以去离自己家最近的邮局发信。

  现在给出了m个备选的邮局,请从中选出k个来,使得村民到自己家最近的邮局的距离和最小。其中两点之间的距离定义为两点之间的直线距离。
输入格式
  输入的第一行包含三个整数n, m, k,分别表示村民的户数、备选的邮局数和要建的邮局数。
  接下来n行,每行两个整数x, y,依次表示每户村民家的坐标。
  接下来m行,每行包含两个整数x, y,依次表示每个备选邮局的坐标。
  在输入中,村民和村民、村民和邮局、邮局和邮局的坐标可能相同,但你应把它们看成不同的村民或邮局。
输出格式
  输出一行,包含k个整数,从小到大依次表示你选择的备选邮局编号。(备选邮局按输入顺序由1到m编号)
样例输入
5 4 2
0 0
2 0
3 1
3 3
1 1
0 1
1 0
2 1
3 2
样例输出
2 4
数据规模和约定
  对于30%的数据,1<=n<=10,1<=m<=10,1<=k<=5;
  对于60%的数据,1<=m<=20;
  对于100%的数据,1<=n<=50,1<=m<=25,1<=k<=10。

 #include <stdio.h>  
 #include <math.h>  
 using