新疆大学ACM-ICPC程序设计竞赛五月月赛(同步赛)

链接:https://www.nowcoder.com/acm/contest/116#question

链接:https://www.nowcoder.com/acm/contest/116/B

杨老师给同学们玩个游戏,要求使用乘法和减法来表示一个数,他给大家9张卡片,然后报出一个数字,要求大家用表达式的形式来表示出这个数
100 可以表示为这样的形式:100 = 129*67-8543 , 还可以表示为:100 = 13*489-6257
注意特征:表达式中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的表达式,100 有 20 种表示法。
题目要求:
从标准输入读入一个正整数N(N<1000 * 1000)
程序输出该数字用数码1~9不重复不遗漏地组成的全部种数。
注意:不要求输出每个表示,只统计有多少表示法!
输入描述:
一个正整数N
输出描述:
输出有多少种表示法
示例1
输入
100
输出
20
备注:
注意只有一个乘法和一个减法,*号保证在-的前面

思路:使用next_permutation()

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

#define mem(a,n) memset(a,n,sizeof(a))
#define rep(i,a,n) for(int i=a;i<n;i++)
#define fre freopen("in.txt","r",stdin)
typedef long long ll;
const ll INF=0x3f3f3f3f;
const int N=1e7+5;

int main()
{
    int n;
    int s[9]= {1,2,3,4,5,6,7,8,9};
    scanf("%d",&n);
    int a,b,c;
    int ans=0;
    do
    {
        a=0;
        for(int i=0; i<9; i++)
        {
            a=a*10+s[i];
            b=0;
            for(int j=i+1; j<9; j++)
            {
                b=b*10+s[j];
                c=0;
                for(int k=j+1; k<9; k++)
                    c=c*10+s[k];
                if(a*b-c==n)
                    ans++;
            }
        }
    }
    while(next_permutation(s,s+9));
    printf("%d\n",ans);
}

链接:https://www.nowcoder.com/acm/contest/116/C
来源:牛客网

题目描述
杨老师认为他的学习能力曲线是一个拱形。勤奋的他根据时间的先后顺序罗列了一个学习清单,共有n个知识点。但是清单中的知识并不是一定要学习的,可以在不改变先后顺序的情况下有选择的进行学习,而每一个知识点都对应一个难度值。杨老师希望,后学习的知识点的难度一定不低于前一个知识点的难度(i<j时ai<=aj),而可能存在一个临界点,在临界点以后,他希望后学习的知识点的难度一定不高于前一个知识点的难度(i<j时ai>=aj)。杨老师想尽可能多的学习知识。请问:杨老师最多可以学习多少知识?
输入描述:
第一行:一个整数n(0<n<500000)接下来一行:n个整数,第i个整数ai(0<=ai<500000)表示第i道题目的难度。
输出描述:
一行一个整数,表示杨老师最多可以学习多少个知识。
示例1
输入
5
1 4 2 5 1
输出
4
思路:DP,两遍最长非递减子序列

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

#define rep(i,a,n) for(int i=a;i<n;i++)
#define mem(a,n) memset(a,n,sizeof(a))
#define pb push_back
#define IO ios::sync_with_stdio(false);
typedef long long ll;
const int N=5e5+5;
const double eps=1e-4;
const int MOD=1e9+7;
const int dir[4][2]= {-1,0,1,0,0,-1,0,1}; ///上下左右
const int INF=0x3f3f3f3f;

int a[N];
int dp[N];
int sum1[N],sum2[N];
int n;
void init()
{
    for(int i=0;i<=n;i++) dp[i]=INF;
}
int main()
{
    int T;
    while(~scanf("%d",&n))
    {
        init();
        for(int i=0; i<n; i++)
        {
            scanf("%d",&a[i]);
            *upper_bound(dp,dp+n,a[i])=a[i];
            sum1[i]=lower_bound(dp,dp+n,INF)-dp;
        }
        init();
        for(int i=n-1;i>=0;i--)
        {
            *upper_bound(dp,dp+n,a[i])=a[i];
            sum2[i]=lower_bound(dp,dp+n,INF)-dp;
        }
        int ans=1;
        for(int i=0;i<n;i++)
        {
            ans=max(ans,sum1[i]+sum2[i]-1);
        }
        printf("%d\n",ans);
    }
    return 0;
}

链接:https://www.nowcoder.com/acm/contest/116/F
来源:牛客网

题目描述
我们知道有一种神奇的排序方法叫做猴子排序,就是把待排序的数字写在卡片上,然后让猴子把卡片扔在空中,等落下的时候观察这些卡片是否从左到右已经排序完成(我们认为不会发生卡片落地后叠在一起的情况)如果有序则排序完成,否则让猴子再扔一遍,直到卡片有序,那么问题来了,给你N个卡片,每个卡片上写着一个大写字母,请问猴子第一次扔这些卡片就按字典序排序完成的概率有多大?

输入描述:
第一行是一个整数N(1<N<100)表示给猴子N张卡片,接下来是一个长度为N的字符串,代表这些卡片上所写的字母。
输出描述:
输出一行,表示猴子排序第一次就成功的概率(用分子为1的分数表示)。
示例1
输入
7
SCIENCE
输出
1/1260
思路:分析题目得到ans = 1/(N!/(A1!A2!……*An!) ,大概Ai为每个字符出现的次数
然后大数阶乘,可以用Python或Java
Python大法好。。

Python3代码:

n = int(input())
str = input()
ans = 1
tmp = 1
cnt = {}
for i in range(n):
    ans *= (i+1)
cnt = []
for i in range(26):
    cnt.append(0)
for i in str:
    if i.isalpha():
        cnt[ord(i)-65] +=1
for i in cnt:
    if i!=0:
        for j in range(1,i+1):
            tmp *= j
print("1/%d"%(ans//tmp)) # 注意这里必须是 //,不能是/

链接:https://www.nowcoder.com/acm/contest/116/G
来源:牛客网

题目描述
A single chess queen is placed somewhere on a grid of 10000*10000 squares.Lao Wang and Xiao Ren ready to play a game The rules are player can move the queen towards the lower left corner of the grid: south, west, or southwest, any number of steps. The winner is the player who moves the queen into the southwest corner.If you let the old Xiao Ren first chess .Suppose they will use the best strategy who will win the game?

输入描述:
The input will consist of a series of pairs of integers a and b, Indicates the distance from the west boundary and the distance from the south boundary.
输出描述:
For each pair of input integers a and b you should output the winner’s name in one line;
示例1
输入
1 2
3 5
1 1
3 2
输出
Lao Wang
Lao Wang
Xiao Ren
Xiao Ren

思路: 博弈模板题,

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

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        if(n>m)swap(n,m);
        int x=(1+sqrt(5))/2*(m-n);
        if(n==x) printf("Lao Wang\n");
        else printf("Xiao Ren\n");
    }
    return 0;
}

链接:https://www.nowcoder.com/acm/contest/116/H
来源:牛客网

题目描述
Once there was a king called XOR, he had a lot of land. Because of his name, he likes to play XOR games.

One day, he whimpered and wanted to establish N cities on that vast expanse of land, numbered 0, 1, 2…, N-1. He wanted to connect all the cities. If city A can reach City B through zero or one or several cities, then A and B are connected. The cost of repairing a road in City A and City B is the XOR value of number of City A and number of City B. This King XOR wanted to figure out the minimum cost for connecting all of the N cities.

Of course, like a fairy tale read as a child, there will be corresponding rewards after helping the king. If you help the king solve his problems, he will improve your ranking in the competition.

输入描述:
There are multi test cases
each test cases contains an integer N (2 ≤N≤ 20000), the number of cities the king wants to establish.
输出描述:
For each test case, print the minimum cost for connecting all of the N cities in one line.
示例1
输入
4
输出
4
说明
The weightof the minimum cost is 1+2+1=4 In the Sample Example.

题意:要建一颗有n个节点的树,权值为两个节点的异或和,求最小的总权值和。

思路:分析可得, 结果为他们的部分和(即两个相邻两个数的最低位1对应的十进制数)

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

#define rep(i,a,n) for(int i=a;i<n;i++)
#define mem(a,n) memset(a,n,sizeof(a))
#define pb push_back
#define IO ios::sync_with_stdio(false);
typedef long long ll;
const int N=2e4+5;
const double eps=1e-4;
const int MOD=1e9+7;
const int dir[4][2]= {-1,0,1,0,0,-1,0,1}; ///上下左右
const int INF=0x3f3f3f3f;

ll lb[N],ans[N];
void init()
{
    for(int i=1;i<=20000;i++) lb[i]=i&(-i);
    ans[1]=lb[1];
    for(int i=2;i<=20000;i++) ans[i]=ans[i-1]+lb[i];
}
int main()
{
    int n;
    init();
    while(~scanf("%lld",&n))
    {
        printf("%lld\n",ans[n-1]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值