The 2016 ACM-ICPC Asia Dalian Regional Contest---题解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37868325/article/details/82932491

A - Wrestling Match(二分图染色/2-set/dfs瞎搞均可)

 题意:

Nowadays, at least one wrestling match is held every year in our country. There are a lot of people in the game is “good player”, the rest is “bad player”. Now, Xiao Ming is referee of the wrestling match and he has a list of the matches in his hand. At the same time, he knows some people are good players,some are bad players. He believes that every game is a battle between the good and the bad player. Now he wants to know whether all the people can be divided into “good player“ and “bad player“.

Input

Input contains multiple sets of data. For each set of data,there are four numbers in the first line: N (1 ≤ N ≤ 1000), M (1 ≤ M ≤ 10000), X, Y (X +Y ≤ N),in order to show the number of players (numbered 1 to N), the number of matches, the number of known “good players“ and the number of known “bad players“. In the next M lines, each line has two numbers a, b (a ̸= b),said there is a game between a and b. The next line has X different numbers. Each number is known as a “good player“ number. The last line contains Y different numbers. Each number represents a known “bad player“ number. Data guarantees there will not be a player number is a good player and also a bad player.

Output

If all the people can be divided into “good players“ and “bad players”, output ‘YES’, otherwise output ‘NO’.

思路:题意真是**了,好不容易才猜对了题意。。是要判M条件是否矛盾。。但是一直读的题意理解的都是不用判,,

知道题意,就简单了,可以用二分图染色,可以2-sat,,那我就比较厉害了,,我啥都没有,一个dfs随便搞搞,记录下颜色,就A了,可怕的是猜题意猜了5个代码才A的,。,,

代码:

#include <bits/stdc++.h>
using namespace std;
struct AA
{
    int x,next;
}pos[30005];
int k,N,M,ans,a,b,x,rt,y,ok,f[2005],vis[2005];
void dfs(int p,int fa,int num)
{
    if(vis[p]==0) vis[p]=num;
    else if(vis[p]!=num) {ans=1;return;}
    int v;
    for(int i=f[p];i!=-1;i=pos[i].next)
    {
        v=pos[i].x;
        //cout<<p<<" "<<v<<" "<<vis[v]<<" "<<fa<<" "<<num<<endl;
        if(vis[v]==0)
        dfs(v,p,num==1?2:1);
        else if(vis[v]!=(num==1?2:1)) {ans=1;return;}
        else continue;
        if(ans) return;
    }
}
int main()
{
    while(~scanf("%d%d%d%d",&N,&M,&x,&y))
    {
        ans=0;
        for(int i=0;i<=N;i++)
            vis[i]=0,f[i]=-1;
        k=0;
        for(int i=1;i<=M;i++)
        {
            scanf("%d%d",&a,&b);
            pos[++k].x=b;
            pos[k].next=f[a];
            f[a]=k;

            pos[++k].x=a;
            pos[k].next=f[b];
            f[b]=k;
        }
        for(int i=1;i<=x;i++)
        {
            scanf("%d",&rt);
            dfs(rt,-1,1);
        }
        for(int i=1;i<=y;i++)
        {
            scanf("%d",&rt);
            dfs(rt,-1,2);
        }
        for(int i=1;i<=N;i++)
        {
            if(vis[i]==0)
            {
                dfs(i,-1,1);
               // break;
            }
        }
        for(int i=1;i<=N;i++)
        {
            if(vis[i]!=0) continue;
            ans=1;
            break;
        }
        if(ans==1)
        {
            printf("NO\n");
        }
        else printf("YES\n");
    }
}

C - Game of Taking Stones(威佐夫博弈+大数+高精度)

题意:

Two people face two piles of stones and make a game. They take turns to take stones. As game rules, there are two different methods of taking stones: One scheme is that you can take any number of stones in any one pile while the alternative is to take the same amount of stones at the same time in two piles. In the end, the first person taking all the stones is winner. Now, giving the initial number of two stones, can you win this game if you are the first to take stones and both sides have taken the best strategy?

Input

Input contains multiple sets of test data.Each test data occupies one line, containing two non-negative integers a and b, representing the number of two stones. a and b are not more than 10100 .

Output

For each test data, output answer on one line. ‘1’ means you are the winner, otherwise output ‘0’.

思路:算一下sqrt(5),代公式就可以了。

代码:


import java.math.BigInteger;

import java.math.BigDecimal;

import java.util.*;

 

public class Main {

	public static void main(String[] args)

	{

		Scanner scanner = new Scanner(System.in);

		BigDecimal TWO = BigDecimal.valueOf(2);

		BigDecimal FIVE = BigDecimal.valueOf(5);

		

		BigDecimal EPS = new BigDecimal("-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001");

		

		BigDecimal L = new BigDecimal("2.2360679774997");

		BigDecimal R = new BigDecimal("2.2360679774998");

		BigDecimal mid = null;

		

		while(L.subtract(R).compareTo(EPS) < 0)

		{

			mid = L.add(R).divide(TWO);

			if(mid.multiply(mid).subtract(FIVE).abs().compareTo(EPS.abs()) < 0)

				break;

			if(mid.multiply(mid).subtract(FIVE).compareTo(EPS) < 0)

				L = mid;

			else

				R = mid;

		}

		

		BigDecimal GOLD = mid.add(BigDecimal.ONE).divide(TWO);

		//System.out.println(GOLD);

		

		while(scanner.hasNext())

		{

			BigDecimal a = scanner.nextBigDecimal();

			BigDecimal b = scanner.nextBigDecimal();

			if(a.compareTo(b) > 0) //保证a是小的

			{

				BigDecimal t = a;

				a = b;

				b = t;

			}

			BigDecimal c = b.subtract(a).multiply(GOLD);

			

			BigInteger aa = a.toBigInteger();

			BigInteger cc = c.toBigInteger();

			if(aa.equals(cc))

				System.out.println("0");

			else 

				System.out.println("1");

		}

	}

}

D - A Simple Math Problem(数学推公式/用素数枚举x,y均可)

题意:

 Given two positive integers a and b, find suitable X and Y to meet the conditions:

X + Y = a

Least Common Multiple(X, Y ) = b

Input

Input includes multiple sets of test data. Each test data occupies one line,including two positive integers a (1 ≤ a ≤ 2 ∗ 104 ), b (1 ≤ b ≤ 109 ), and their meanings are shown in the description.

Output

For each set of input data,output a line of two integers, representing X, Y . If you cannot find such X and Y , output one line of ‘No Solution’ (without quotation).

思路:数学的题,太坑了!!输出的x,y要符合x<=y!!!但是题意一点没提!!!因为这WA了一个半小时多!!

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

bool flag;
ll a,b,len,ansx,ansy;
ll p[105],num[105];

void init(ll n)
{
    len=0;
    for(ll i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            p[++len]=i;
            num[len]=0;
        }
        while(n%i==0)
        {
            num[len]++;
            n=n/i;
        }
    }
    if(n>1)
    {
        p[++len]=n;num[len]=1;
    }
}

ll fpow(ll n,ll x)
{
    ll ans=1;
    for(int i=1;i<=x;i++)
        ans=ans*n;
    return ans;
}

void dfs(ll step,ll sum1,ll sum2)
{
    for(int i=0;i<num[step];i++)
    {
        if(flag) return;
        if(step<len)
        {
            dfs(step+1,sum1*fpow(p[step],i),sum2*fpow(p[step],num[step]));
        }
        else
        {
            ll x=sum1*fpow(p[step],i);
            ll y=sum2*fpow(p[step],num[step]);
            //cout<<x<<"            "<<y<<endl;
            if(x+y==a)
            {
                flag=true;
                ansx=x;ansy=y;
                return;
            }
        }
    }
    for(int i=0;i<=num[step];i++)
    {
        if(flag) return;
        if(step<len)
        {
            dfs(step+1,sum1*fpow(p[step],num[step]),sum2*fpow(p[step],i));
        }
        else
        {
            ll x=sum1*fpow(p[step],num[step]);
            ll y=sum2*fpow(p[step],i);
            //cout<<x<<" "<<y<<endl;
            if(x+y==a)
            {
                flag=true;
                ansx=x;ansy=y;
                return;
            }
        }
    }
}

int main()
{
    while(scanf("%lld%lld",&a,&b)!=EOF)
    {
        if(a==1)
        {
            printf("No Solution\n");
            continue;
        }
        if(b==1)
        {
            if(a==2)
                printf("1 1\n");
            else
                printf("No Solution\n");
            continue;
        }
        init(b);
        /*for(int i=1;i<=len;i++)
        {
            cout<<p[i]<<" "<<num[i]<<endl;
        }*/
        flag=false;
        dfs(1ll,1ll,1ll);
        if(flag)
        {
            if(ansx>ansy) swap(ansx,ansy);
            printf("%lld %lld\n",ansx,ansy);
        }
        else
            printf("No Solution\n");
    }
    return 0;
}

F - Detachment(贪心)

题意:

In a highly developed alien society, the habitats are almost infinite dimensional space. In the history of this planet,there is an old puzzle. You have a line segment with x units’ length representing one dimension. The line segment can be split into a number of small line segments: a1, a2, . . . (x = a1+a2+. . . ) assigned to different dimensions. And then, the multidimensional space has been established. Now there are two requirements for this space: 1. Two different small line segments cannot be equal (ai ̸= aj when i ̸= j). 2. Make this multidimensional space size s as large as possible (s = a1 ∗ a2 ∗ . . .). Note that it allows to keep one dimension. That’s to say, the number of ai can be only one. Now can you solve this question and find the maximum size of the space? (For the final number is too large,your answer will be modulo 109 + 7)

Input

The first line is an integer T, meaning the number of test cases. Then T lines follow. Each line contains one integer x. 1 ≤ T ≤ 106 , 1 ≤ x ≤ 109

Output

Maximum s you can get modulo 109 + 7. Note that we wants to be greatest product before modulo 109 + 7

思路:贪心,先二分找最大的 l,,2---l 的和小<=x.,然后把剩余的值k,分给后面的k个数,如果每个都分了1后还余1,就让最后一个再加1.跟着代码分析分析更好理解。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define MAXN 50000
#define mod 1000000007
int T;
ll ans,x,z,inv[MAXN],fac[MAXN],invv[MAXN];
ll pow_mod(ll n,ll k)
{
    ll res=1;
    while(k>0)
    {
        if(k&1)
            res=res*n%mod;
        n=n*n%mod;
        k>>=1;
    }
    return res;
}

void init_fac()
{
    fac[0]=fac[1]=inv[1]=invv[1]=1;
    for(int i=2;i<MAXN;++i)
    {
        fac[i]=i*fac[i-1]%mod;
        inv[i]=pow_mod(i,mod-2);
        invv[i]=invv[i-1]*inv[i]%mod;
    }
}
int main()
{
    init_fac();
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld",&x);
        if(x<=3) {printf("%d\n",x);continue;}
        ll l=0,r=x+1,mid=-1;
        while(1)
        {
            if(mid==(l+r)/2) break;
            mid=(l+r)/2;
            if((mid+2)*(mid-1)/2>x) r=mid;
            else l=mid;
        }
        ans=1;
        z=(l+2)*(l-1)/2-x;
        if(z==0)
        {
            printf("%lld\n",fac[l]);
            continue;
        }
        z=(r+2)*(r-1)/2-x;
        if(z==1)
        {
            ans=fac[l]*inv[2]%mod;
            ans*=(r+1);
            ans%=mod;
            printf("%lld\n",ans);
            continue;
        }
        else
        {
        z=x-(l+2)*(l-1)/2;
           if(z<=l-1)
           {
               ans=fac[l+1]*invv[l-z+1]%mod;
               ans*=fac[l-z];
               ans%=mod;
           }
            else
            {
                ans=fac[l]*inv[2]%mod;
                ans*=(l+2);
                ans%=mod;
            }
            printf("%lld\n",ans);
                continue;
        }
    }


}

H - To begin or not to begin(概率知识点,水题)

 题意:

A box contains black balls and a single red ball. Alice and Bob draw balls from this box without replacement, alternating after each draws until the red ball is drawn. The game is won by the player who happens to draw the single red ball. Bob is a gentleman and offers Alice the choice of whether she wants to start or not. Alice has a hunch that she might be better off if she starts; after all, she might succeed in the first draw. On the other hand, if her first draw yields a black ball, then Bob’s chances to draw the red ball in his first draw are increased, because then one black ball is already removed from the box. How should Alice decide in order to maximize her probability of winning? Help Alice with decision.

Input

Multiple test cases (number of test cases ≤ 50), process till end of input. For each case, a positive integer k (1 ≤ k ≤ 105 ) is given on a single line.

Output

For each case, output: • ‘1’, if the player who starts drawing has an advantage • ‘2’, if the player who starts drawing has a disadvantage • ‘0’, if Alice’s and Bob’s chances are equal, no matter who starts drawingon a single line.

思路:k是指黑球数量。。。算是一个比较好猜的题意 了,然后就简单了,概率定理,,每次抽,赢的概率一样,所以只可能有0 1的存在,根据奇偶判判就行,

代码:

#include<bits/stdc++.h>
using namespace std;

int N,a,b,c,l,ans;

int main()
{
    while(~scanf("%d",&N))
    {
        if(N%2==0)
        printf("1\n");
        else
            printf("0\n");
    }
    return 0;
}

I - Convex(正弦定理)

 题意:

We have a special convex that all points have the same distance to origin point. As you know we can get N segments after linking the origin point and the points on the convex. We can also get N angles between each pair of the neighbor segments. Now give you the data about the angle, please calculate the area of the convex

Input

There are multiple test cases. The first line contains two integer N and D indicating the number of the points and their distance to origin. (3 ≤ N ≤ 10, 1 ≤ D ≤ 10) The next lines contain N integers indicating the angles. The sum of the N numbers is always 360.

Output

For each test case output one float numbers indicating the area of the convex. The printed values should have 3 digits after the decimal point.

思路:

就是正弦定理 ,但是一开始用的余弦定理WA了,,,大概是余弦步骤太多,导致精度不够,,,醉醉的

代码:

#include <bits/stdc++.h>
using namespace std;
const double PI=acos(-1.0);

double area(double a,double b,double c)
{
    double p=(a+b+c)/2.0;
    return sqrt(p*(p-a)*(p-b)*(p-c));
}

double angle(double x)
{
    return (x*PI/180.0);
}

int N,DD;
double aa;

int main()
{
    while(cin>>N>>DD)
    {
        double ans=0,D=1.0*DD;
        for(int i=1;i<=N;i++)
        {
            cin>>aa;
            double ta=D*D*sin(angle(aa))/2;
            ans+=ta;
        }
        cout<<fixed<<setprecision(3)<<ans<<endl;

    }
    return 0;
}

J - Find Small A(水题)

题意:

As is known to all, the ASCII of character ‘a’ is 97. Now, find out how many character ‘a’ in a group of given numbers. Please note that the numbers here are given by 32 bits’ integers in the computer. That means,1 digit represents 4 characters (one character is represented by 8 bits’ binary digits).

Input

The input contains a set of test data. The first number is one positive integer N (1 ≤ N ≤ 100), and then N positive integersai (1 ≤ ai ≤ 2 32 − 1) follow in a second line.

Output

Output one line, including an integer representing the number of ‘a’ in the group of given numbers.

思路:猜题意啊猜题意,猜对了就A了,每8位一判断,不能随便的8位。。。

#include<bits/stdc++.h>
using namespace std;

int N,a,b,c,l,ans;
string s1,s2;
int AA()
{
    for(int i=1;i<=8-(s2.size()%8);i++)
        s2+='0';
    l=0;
    for(int i=0;i<s2.size();i+=8)
    {
        c=0;
        for(int j=0;j<s1.size();j++)
        {
            if(s1[j]!=s2[i+j])
            {
                break;
            }
            c++;
            //cout<<i<<" "<<j<<" "<<s1<<" "<<s2<<endl;
        }
        if(c==8) {l++;}
    }
    return l;
}
int main()
{
    b=97;
    while(b)
    {
        s1+=(b%2)+'0';
        b/=2;
    }
    s1+='0';
    while(~scanf("%d",&N))
    {
        ans=0;
        for(int i=1;i<=N;i++)
        {
            scanf("%d",&a);
            s2="";
            while(a)
            {
                s2+=(a%2)+'0';
                a/=2;
            }
            ans+=AA();
        }
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37868325/article/details/82932491