QLU浪在ACM 3.17团队赛

版权声明:转载请带一下我这个小蒟蒻哦~ https://blog.csdn.net/QLU_minoz/article/details/88624505

A - Switch Game

 

There are many lamps in a line. All of them are off at first. A series of operations are carried out on these lamps. On the i-th operation, the lamps whose numbers are the multiple of i change the condition ( on to off and off to on ).

Input

Each test case contains only a number n ( 0< n<= 10^5) in a line. 

Output

Output the condition of the n-th lamp after infinity operations ( 0 - off, 1 - on ).

Sample Input

1
5

Sample Output

1
0

Consider the second test case:

The initial condition	   : 0 0 0 0 0 …
After the first operation  : 1 1 1 1 1 …
After the second operation : 1 0 1 0 1 …
After the third operation  : 1 0 0 0 1 …
After the fourth operation : 1 0 0 1 1 …
After the fifth operation  : 1 0 0 1 0 …

The later operations cannot change the condition of the fifth lamp any more. So the answer is 0.

拨动开关,第i次拨动所有i的整数倍数的开关,问第i次拨动后,第i个开关的情况。其实就是看开关拨动多少次,开始是关 奇数次后是开 ,偶数次后是关。i的因子数就是拨动他的次数。

#include<bits/stdc++.h>
using namespace std;
int n;
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        int ans=0;//ans代表拨动开关的次数
        int i;
        for(i=1;i*i<n;i++)
        {
            if(n%i==0)
            {
                ans++;
            }
        }
        ans*=2;
        if(i*i==n)
            ans+=1;

        if(ans&1)//开始是关 奇数次后是开 
            printf("1\n");
        else//偶数次后是关
            printf("0\n");
    }
}

B - Catch That Cow

Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting. 

* Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute 
* Teleporting: FJ can move from any point X to the point 2 × X in a single minute. 

If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?

Input

Line 1: Two space-separated integers: N and K

Output

Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.

Sample Input

5 17

Sample Output

4

Hint
The fastest way for Farmer John to reach the fugitive cow is to move along the following path: 5-10-9-18-17, which takes 4 minutes.

从n点走到k点,最少需要多少次移动。在任意x点,可以走到x-1,x+1,x*2点处。      
 这个题没说多组输入,让ljp小朋友debug好久。

求最小距离bfs就阔以,话说,我的搜索是真的不行鸭...

//#include<iostream>
//#include<cstdio>
//#include<queue>
//#include<cstring>
//#include<map>
//using namespace std;
//#define INF 0x3f3f3f3f
//#define mem(a,b) memset(a,b,sizeof(a))
//const int maxn=1e6+50;
//
//int x,y;
//int a[maxn];
//int step[maxn];
//queue<int >q;
//
//bool isSat(int val)
//{
//    if(val < 0 || val > 1000000)
//        return false;
//    return step[val] == -1 ? true:false;
//}
//int main()
//{
//    while(~scanf("%d%d",&x,&y))
//    {
//        mem(step,-1);
//        step[x]=0;
//        q.push(x);
//        while(!q.empty())
//        {
//            int index=0;
//            while(!q.empty())
//            {
//                int t=q.front();
//                q.pop();
//                if(isSat(t-1))
//                {
//                    step[t-1]=step[t]+1;
//                    a[index++]=t-1;
//                }
//                if(isSat(t+1))
//                {
//                    step[t+1]=step[t]+1;
//                    a[index++]=t+1;
//                }
//                if(isSat(t*2))
//                {
//                    step[t*2]=step[t]+1;
//                    a[index++]=2*t;
//                }
//            }
//            for(int i=0;i < index;++i)
//                q.push(a[i]);
//        }
//        printf("%d\n",step[y]);
//    }
//    return 0;
//}

#include<bits/stdc++.h>
using namespace std;
const int maxn=100000+5;
int step[maxn*2];//step[i]在i处的步数
int vis[maxn*2];//是否访问 剪枝1.多次访问的话会多次重复此点的三个操作2.避免陷入x->(x-1)->x->(x-1)...的死循环
int n,m;

bool IsSure(int x)//可以到达的点的范围
{
    if(x>=0&&x<=100002*2)
        return true;
    return false;
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(step,-1,sizeof step);
        memset(vis,0,sizeof step);
        queue<int> q;
        step[n]=0;
        vis[n]=1;
        q.push(n);
        while(!q.empty())
        {
            int x=q.front();
            q.pop();
            if(x==m)
                break;
            if( IsSure(x*2) && (!vis[x*2]) )
			{
				vis[2*x] = 1;
				q.push(x*2);
				step[x*2] = step[x]+1;
			}
			if( IsSure(x+1) && (!vis[x + 1]) )
			{
				vis[x+1]=1;
				q.push(x+1);
				step[x+1]=step[x]+1;
			}
			if( IsSure(x-1) && (!vis[x-1]) )
			{
				vis[x-1]=1;
				q.push(x-1);
				step[x-1]=step[x]+1;
			}
        }
        printf("%d\n",step[m]);
    }
}

 

C - Digital Roots

 

The digital root of a positive integer is found by summing the digits of the integer. If the resulting value is a single digit then that digit is the digital root. If the resulting value contains two or more digits, those digits are summed and the process is repeated. This is continued as long as necessary to obtain a single digit. 

For example, consider the positive integer 24. Adding the 2 and the 4 yields a value of 6. Since 6 is a single digit, 6 is the digital root of 24. Now consider the positive integer 39. Adding the 3 and the 9 yields 12. Since 12 is not a single digit, the process must be repeated. Adding the 1 and the 2 yeilds 3, a single digit and also the digital root of 39.

Input

The input file will contain a list of positive integers, one per line. The end of the input will be indicated by an integer value of zero.

Output

For each integer in the input, output its digital root on a separate line of the output.

Sample Input

24
39
0

Sample Output

6
3

这个题很坑啊啊啊!原来还有极大的数,wa了三发才发觉。

一个数a的每一位相加变成b,如果b大于9,就再每一位相加....如此反复直到小于9。其实就是每一位相加对9取余,看余数是多少,注意,9就可以的,也就是如果这个数是9的倍数的话,模9还剩9,即是输出9。由于数可能很大,那就用字符串存咯23333

#include<iostream>
#include<cstdio>
using namespace std;
int sum;
string s;
int main()
{
    while(cin>>s)
    {
        sum=0;
        if(s[0]=='0')
            break;
        int len=s.length();
        for(int i=0;i<len;i++)
            sum+=s[i]-'0';
      //  cout<<"sum:"<<sum<<endl;
        if(sum%9==0)//9的倍数
            printf("9\n");
        else
            printf("%d\n",sum%9);
    }
}

 

D - Doing Homework again

 

Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher gives him a deadline of handing in the homework. If Ignatius hands in the homework after the deadline, the teacher will reduce his score of the final test. And now we assume that doing everyone homework always takes one day. So Ignatius wants you to help him to arrange the order of doing homework to minimize the reduced score.

Input

The input contains several test cases. The first line of the input is a single integer T that is the number of test cases. T test cases follow. 
Each test case start with a positive integer N(1<=N<=1000) which indicate the number of homework.. Then 2 lines follow. The first line contains N integers that indicate the deadlines of the subjects, and the next line contains N integers that indicate the reduced scores. 

Output

For each test case, you should output the smallest total reduced score, one line per test case. 

Sample Input

3
3
3 3 3
10 5 1
3
1 3 1
6 2 3
7
1 4 6 4 2 4 3
3 2 1 7 6 5 4

Sample Output

0
3
5

贪心。想减分最少,当然就是得分最多,可以根据分数,从高到底排序,当分数相同时,先考的科目在前。

可以把一门课放在他的deadline,当deadline有课时,把这一门课相应的往前移。如果前面都排满了(由于是分数从高到低的顺序,先排的分数肯定高)就没有时间排这一门课了,因为已经排了课的分数肯定比这一门课高,就放弃这一门。

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
int vis[1005];
struct node
{
    int t,s;
}e[1005];

bool cmp(node a , node b)
{
    if(a.s==b.s)
        return a.t<b.t;
    else
        return a.s>b.s;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        memset(vis,0,sizeof vis);
        for(int i=1;i<=n;i++)
            scanf("%d",&e[i].t);
        for(int i=1;i<=n;i++)
            scanf("%d",&e[i].s);
        sort(e+1,e+1+n,cmp);

        bool flag=false;
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            int now=e[i].t;
            if(!vis[now])//如果t这一天没有被占
                vis[now]=1;//那就占上
            else//如果被占了
            {
                for(int j=now-1;j>=0;j--)//就从这一天往前找没被占的
                {
                    if(j!=0&&!vis[j])//如果找到
                    {
                        vis[j]=1;//占上
                        break;
                    }
                    if(j==0)//往前找直到第零天,没有第零天所以没找到
                        sum+=e[i].s;//放弃的分数
                }
            }
        }
        printf("%d\n",sum);
    }
}

 

 

 

F - Coin Game

After hh has learned how to play Nim game, he begins to try another coin game which seems much easier. 

The game goes like this: 
Two players start the game with a circle of n coins. 
They take coins from the circle in turn and every time they could take 1~K continuous coins. 
(imagining that ten coins numbered from 1 to 10 and K equal to 3, since 1 and 10 are continuous, you could take away the continuous 10 , 1 , 2 , but if 2 was taken away, you couldn't take 1, 3, 4, because 1 and 3 aren't continuous) 
The player who takes the last coin wins the game. 
Suppose that those two players always take the best moves and never make mistakes. 
Your job is to find out who will definitely win the game.

Input

The first line is a number T(1<=T<=100), represents the number of case. The next T blocks follow each indicates a case. 
Each case contains two integers N(3<=N<=10 9,1<=K<=10).

Output

For each case, output the number of case and the winner "first" or "second".(as shown in the sample output)

Sample Input

2
3 1
3 2

Sample Output

Case 1: first
Case 2: second

博弈题。(话说上午刚看了四大基本博弈,就遇到了博弈题,虽然并不是四大博弈,但也提供了思路)

先特判k=1和k>=n的情况,此为奇异局势。在非奇异局势,第一个人第一次不可能拿走全部的coin,对于剩下的coin,记为m个,如果k>=m则第二个人一次就能拿走全部的coin,那么第二个人就赢了;如果不能,说明m>k>=2,则m至少为3,所以第二个人一定可以拿走一些连续的coin,将剩下的coin变成长度相等的两条链,此后第二个人只要模仿第一个人的操作:即第一个人在某一堆拿走了一些coin,第二个人就在另一堆拿走等量的coin,最后便会获胜。

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    int t;
    cin>>t;
    for(int i=1;i<=t;i++)
    {
        int n,k;
        scanf("%d%d",&n,&k);
        printf("Case %d: ",i);
        if(k>=n)
            printf("first\n");
        else if(k==1)
        {
            if(n&1)
                printf("first\n");
            else
                printf("second\n");
        }
        else
            printf("second\n");
    }
}

L - Constructing Roads

There are N villages, which are numbered from 1 to N, and you should build some roads such that every two villages can connect to each other. We say two village A and B are connected, if and only if there is a road between A and B, or there exists a village C such that there is a road between A and C, and C and B are connected. 

We know that there are already some roads between some villages and your job is the build some roads such that all the villages are connect and the length of all the roads built is minimum.

Input

The first line is an integer N (3 <= N <= 100), which is the number of villages. Then come N lines, the i-th of which contains N integers, and the j-th of these N integers is the distance (the distance should be an integer within [1, 1000]) between village i and village j. 

Then there is an integer Q (0 <= Q <= N * (N + 1) / 2). Then come Q lines, each line contains two integers a and b (1 <= a < b <= N), which means the road between village a and village b has been built.

Output

You should output a line contains an integer, which is the length of all the roads to be built such that all the villages are connected, and this value is minimum.

Sample Input

3
0 990 692
990 0 179
692 179 0
1
1 2

Sample Output

179

给定n个点之间的距离,然后Q次改变某两个点之间的距离成0,求最小生成树。

由于kruskal用的比较熟练,prim算法不太会23333,就把邻接矩阵重新读入到vector数组中用kruskal来做了QAQ,其实这种稠密图还是prim比较好

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
using namespace std;
#define INF 0x3f3f3f3f
int pre[105];
int G[105][105];
int n;
int sum;
struct Edge
{
    int u,v,w;
}p;
vector<Edge> GG;
bool cmp(Edge a,Edge b)//从小到大排序
{
    return a.w<b.w;
}


void Init()
{
    sum=0;
    for(int i=0;i<=n;i++)
    {
        pre[i]=i;
    }
}

void addedge(int u,int v,int w)//加边
{
    p.u=u;
    p.v=v;
    p.w=w;;
    GG.push_back(p);
}

int Find(int x)
{
    return x == pre[x] ? x:pre[x]=Find(pre[x]);
}

bool mix(int x,int y)
{
    int fx=Find(x),fy=Find(y);
    if(fx!=fy)
    {
        pre[fx]=fy;
        return true;
    }
    return false;
}

int kruskal()
{
    sort(GG.begin(),GG.end(),cmp);
    for(int i=0;i<GG.size();i++)
    {
        if(mix(GG[i].u,GG[i].v))
            sum+=GG[i].w;
    }
    return sum;
}

int main()
{
    while(~scanf("%d",&n))
    {
        Init();
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&G[i][j]);
            }
        }
        int k;
        scanf("%d",&k);
        while(k--)//边长修改为0
        {
            int x,y;
            scanf("%d%d",&x,&y);
            G[x][y]=0;
        }
        //往vector里加边
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j)
                    continue;
                addedge(i,j,G[i][j]);
            }
        }
        printf("%d\n",kruskal());
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/QLU_minoz/article/details/88624505