EOJ Monthly 2017.12 A+B+C

A. 唐纳德先生和假骰子

Time limit per test: 1.0 seconds

Memory limit: 256 megabytes

在进行某些桌游,例如 UNO 或者麻将的时候,常常会需要随机决定从谁开始。骰子是一种好方案。普通的骰子有六个面,分别是一点、二点、三点、四点、五点、六点,六面向上的概率相同。由于骰子只能产生六种情况,而实际桌游时,却常常有三到四人,所以,我们在掷骰子时,常常采用两颗骰子,这个「随机的选择」就由骰子向上点数之和直接决定。

我们采用这么一种方案,将向上点数之和对  p (人数)取模,模出来的  0,1,,p1  恰好对应  p  个人。但这并不一定是公平的。例如,如果你有算过的话,两枚普通的骰子,在四个人的情形下,就是不公平的。

所以唐纳德先生发明了一种假骰子,这种假骰子也有六个面,但六个面的点数就不再是  1,2,3,4,5,6 ,而是  a1,a2,a3,a4,a5,a6 。如果他精心选择了这六个面的点数,他仍然可以强制公平。

先给出  p  和两枚假骰子六个面的点数,问是否公平。

Input

输入具有如下形式:

pa1 a2 a3 a4 a5 a6b1 b2 b3 b4 b5 b6

第一行一个整数  p  ( 3p4 )。

第二行六个整数,用空格隔开,表示第一枚骰子的点数  a1,a2,a3,a4,a5,a6  ( 1ai6 )。

第三行六个整数,用空格隔开,表示第二枚骰子的点数  b1,b2,b3,b4,b5,b6  ( 1bi6 )。

Output

如果公平输出 YES,否则输出 NO

Examples

input
4
1 2 3 4 5 6
1 2 3 4 5 6
output
NO
input
3
1 2 3 4 5 6
6 5 4 3 2 1
output

YES

直接暴力模拟

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
#define MOD 1000000007
#define N 400010
int map1[7];
int map2[7];
int map[37];
int main()
{
    int n;
    while(cin>>n)
    {
        memset(map,0,sizeof(map));
        for(int i=1;i<=6;i++)
            scanf("%d",&map1[i]);
        for(int i=1;i<=6;i++)
            scanf("%d",&map2[i]);
        for(int i=1;i<=6;i++)
        {
            for(int j=1;j<=6;j++)
            {
                map[(map1[i]+map2[j])%n]++;
            }
        }
        int flag=1;
        for(int i=0;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
                if(map[i]!=map[j])
                    flag=0;
        }
        if(flag==1)
            cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

B. 在哈尔滨的寒风中

Time limit per test: 1.0 seconds

Memory limit: 256 megabytes

kblack 来到了寒冬中的哈尔滨,哈尔滨的寒风令 kblack 瑟瑟发抖。

世界上最远的距离,是你与宾馆只差一条冰街,而你却忘了穿上秋裤。

kblack 终于冲进了宾馆,宾馆大厅的地板铺满了五颜六色的地砖,可以被看作是一块  n×m  格的棋盘,为了能使冻僵了的双脚尽快暖和起来,kblack 决定在地砖上走动,但是他被速冻的双脚在棋盘地板上只能走马步。

kblack 居然想知道有多少对地砖(无序点对)他可以通过若干步马步互相抵达!

Input

输入包含一行两个正整数  n m ,表示棋盘的大小,保证  1n×m109  。

Output

输出包含一个整数,表示 kblack 可以通过马步互相到达的无序地砖对数。

Examples

input
1 2
output
0
input
4 2
output
4
开始的思路是搜索,底层每个格子当做起点开始,因为是无序的,所以只向上搜索,到顶层结束,深度便是需要的对数,一直在中间测试部分超时

其实一看数据就知道是有规律的,就是没想出来。。。

今天看了解题报告才做恍然大悟状,超过3*4的棋盘,是可以两两到达的,根据题解思路写了份代码,算是间接 A了吧

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
#define ll long long
#define MOD 1000000007
#define N 100010
int dx[]={-2,-1,1,2};
int dy[]={1,2,2,1};
int n,m;
ll gcd(ll a,ll b)
{
    if(b==0)
        return a;
    return gcd(b,a%b);
}
int judge(int x,int y)
{
    if(x<=n&&x>=1&&y>=1&&y<=m)
        return 1;
    return 0;
}
ll CC(int n,int m)
{
    ll ans=1;
    if(n<m)
        return 0;
        else if(n==m)
            return 1;
    int j=2;
    ll temp=1;
    int a=max(m,n-m);
    int b=min(m,n-m);

    for(int i=n;i>a;i--)
    {
        ans*=i;
        if(j<=b||temp>1)
        {
            if (j<=b)
            temp*=j;
            if (temp>1)
            {
                ll GCD=gcd(ans,temp);
                ans/=GCD;
                temp/=GCD;
            }
        }
        j++;
    }
    return ans;
}
int main()
{
    while(cin>>n>>m)
    {
        /*if(min(n,m)<2)
        {
            cout<<0<<endl;
            continue;
        }
        ans=0;
        for(int j=1;j<m;j++)
        {
            for(int i=1;i<=n;i++)
            {
                //cout<<"i  j "<<i<<" "<<j<<endl;
                dfs(i,j,0);
            }
        }*/
        if(min(n,m)==1)
            cout<<0<<endl;
            else if(max(n,m)==2)
                cout<<0<<endl;
        else if(n==3&&m==3)
            cout<<CC(8,2)<<endl;
        else if(m==2)
            cout<<2*CC(n/2,2)+2*CC(n-n/2,2)<<endl;
            else if(n==2)
                cout<<2*CC(m/2,2)+2*CC(m-m/2,2)<<endl;
        else if(m*n>=3*4)
            cout<<CC(n*m,2)<<endl;
    }

C. 易位构词

Time limit per test: 2.0 seconds

Memory limit: 256 megabytes

易位构词 (anagram),指将一个单词中的字母重新排列,原单词中的每个字母都出现有且仅有一次。例如 "unce" 可以被易位构词成 "ecnu"。在某些情况下,要求重排而成的依然是一个单词,但本题没有这种要求,因为我们根本没有词典。

我们所感兴趣的是,有些单词中的字母进行适当的重排后,可以使得构成的单词每个对应的位置上字母都不一样。例如 "unce" 和 "ecnu",就有 "u"   "e", "n"   "c", "c"   "n", "e"   "u"。现在给出一个单词,问是否存在这样一个重排。

Input

一行一个单词  s  ( 1|s|105 )。单词完全由  26  个小写英文字母构成。

Output

输出一个单词。如果有多解,输出任意解。如果不存在,输出 impossible

Examples

input
unce
output
ecnu
input
aaaaaa
output
impossible
显然最多的字母出现次数大于一半的情况是不行的。否则就将每个字母的位置和字母绑定一下,
按字母序对结构体进行排序。然后右移「出现最多的字母出现次数」位,再排回来就可以了
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
#define ll long long
#define MOD 1000000007
#define N 100005
int num[256];
char s[N],temp[N];
char ans[N];
struct node
{
    char c;
    int p;
}map[N];
bool cmp(node a,node b)
{
    return num[a.c]>num[b.c]||(num[a.c]==num[b.c]&&a.c<b.c);
}
int main()
{
    scanf("%s",s);
    int len=strlen(s);
    int ma=0;
    for(int i=0;i<len;i++)
    {
        map[i].c=s[i];
        map[i].p=i;
        num[s[i]]++;
        if(num[s[i]]>ma)
            ma=num[s[i]];
    }
    sort(map,map+len,cmp);
    if((ma*2)>len)
        cout<<"impossible"<<endl;
    else
    {

        for(int i=0;i<len;i++)
            temp[(i+ma)%len]=map[i].c;
        for(int i=0;i<len;i++)
            ans[map[i].p]=temp[i];
        cout<<ans<<endl;
    }

    return 0;
}

还一个字符串水题水过了easy的(暴力查找子串),hard一直超时,不发了



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值