中软ACM周赛 - Round 9

中软ACM周赛 - Round 9

问题 A: WA哭了

题目描述
XX又又又又双叒叕哭了,大家快来帮帮他.
那么现在给你 A,C,W 三种字符,问组成一个长度为 n(不含 WA,即 W 后一个字符不能为 A ) 的字符串,总共有多少种方案?( T 组数据)

输入
先输入一个T,表示有T组数据,
然后输入需要组成字符串的长度ni(1<=i<=T)
1 <= T <= 40
1 <= ni <= 40

输出
对于每个ni 输出对应的答案

样例输入
2
1
2

样例输出
3
8

在纸上随便画画就可以发现一个简单的递推公式
#include<iostream>
#include<cstring>
#include<cstdio>
//#define LOCAL
using namespace std;
typedef long long ll;
ll s[10010]={0,3,8};
int main()
{
    #ifdef LOCAL
        freopen("C:\\Users\\Dell\\Desktop\\in.txt", "r", stdin);
        freopen("C:\\Users\\Dell\\Desktop\\out.txt", "w", stdout);
    #endif

        int a;

        for(int i=3;i<=10000;i++) // 此处也可以提前打好表
            s[i]=3*s[i-1]-s[i-2];
        int n;  cin >> n;
        while(n--){
            cin >> a;
            cout << s[a] << endl;
        }
        return 0;
}

问题 B: XX的签到题
题目描述
输出下图Orz

输入

输出

样例输出

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\   /@@@@@\    \@@/@@  @@@@@@@@@   \\
\\  @@/   \@@    @@@[        /@@"   \\
\\ @@@     @@@   @@         @@/     \\
\\ @@       @@   @@       /@@       \\
\\ @@@     @@@   @@      @@@        \\
\\  @@@\]/@@/    @@     @@@@@@@@@   \\
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

总所周知,输出字符也是一门学问(/手动滑稽)
#include<iostream>
#include<cstring>
#include<cstdio>
//#define LOCAL
using namespace std;
typedef long long ll;
ll nums[100010]={0};
ll a[100010]={0};
ll n,t,ans;
int main()
{
    #ifdef LOCAL
        freopen("C:\\Users\\Dell\\Desktop\\in.txt", "r", stdin);
        freopen("C:\\Users\\Dell\\Desktop\\out.txt", "w", stdout);
    #endif
 
        cout << "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"<<endl;
        cout << "\\\\   /@@@@@\\    \\@@/@@  @@@@@@@@@   \\\\" << endl;
        cout << "\\\\  @@/   \\@@    @@@[        /@@\"   \\\\" << endl;
        cout << "\\\\ @@@     @@@   @@         @@/     \\\\" << endl;
        cout << "\\\\ @@       @@   @@       /@@       \\\\" << endl;
        cout << "\\\\ @@@     @@@   @@      @@@        \\\\" << endl;
        cout << "\\\\  @@@\\]/@@/    @@     @@@@@@@@@   \\\\" << endl;
        cout << "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" << endl;
    return 0;
}

问题 C: XX组队
题目描述
在XX的徒弟中,每一名徒弟都有一个能力值。现在XX想挑选一个两人小组,他有个奇怪的要求,
需要这两名徒弟的能力值加起来和XX一个期望的值一样,现在请你帮忙计算他有多少种挑选徒弟组成小组的方式,注意不同徒弟能力值可能相同。

输入
第一行一个整数n(2<=n<=100000)和一个整数t(1<=t<=100000), 表示XX徒弟的个数和他期望的值,
接下来一行有n个非负整数,第i个非负整数表示第i名徒弟的能力值,其中每名徒弟的能力值都不会超过t。

输出
输出一行,表示XX能挑选出一个2人小组的方案数

样例输入
4 5
2 3 3 2

样例输出
4

提示
样例解释:
可以选择的方式有(1,2),(1,3),(2,4),(3,4)共四种

做法很多,先标记每个能力值

 1. 两个能力值之和为T时,可行方案数为两者对应徒弟数之积,当能力值时T/2时方案数为n*(n-1)/2
 2. 计算每个徒弟可以和多少人成功组队

需要注意一下数据范围,会超int呦
下面给出第二种做法的代码
#include<iostream>
#include<cstring>
#include<cstdio>
//#define LOCAL
using namespace std;
typedef long long ll;
ll nums[100010]={0};
ll a[100010]={0};
ll n,t,ans;
int main()
{
    #ifdef LOCAL
        freopen("C:\\Users\\Dell\\Desktop\\in.txt", "r", stdin);
        freopen("C:\\Users\\Dell\\Desktop\\out.txt", "w", stdout);
    #endif
        cin >>n >> t;
        for(ll i=0;i<n;i++){
            cin >> a[i];
            nums[a[i]]++;
        }
        for(ll i=0;i<n;i++){
            if(nums[t-a[i]]>0){
                if(t-a[i]==a[i]) ans+=nums[t-a[i]]-1;
                else ans+=nums[t-a[i]];
                nums[a[i]]--;
            }
        }
        cout << ans;
    return 0;
}

问题 D: XX的猜想
题目描述
失业后 XX在家里苦学数学 这一天他看到了哥德巴赫猜想:任意偶数n都能被拆分为俩质数(n>2) 现在XX重拾他的老本行来证明他的猜想

输入
输入一个偶数n(n>2&&n<100000)

输出
输出有多少对满足哥德巴赫猜想的例子

样例输入
6

样例输出
1

提示
6能拆为3和3

哥德巴赫猜想,?
打个素数表就OK了
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
bool Is_prime[100011]={1,1};
int prime[100011];
int num=0;
const int maxn = 100011;
bool ju(int n)
{
    for(int i=2;i<(int)(sqrt(n)+1);i++){
        if(!n%i) return false;
    }
    return true;
}
void rep()
{
     for(int i=2;i<maxn;i++){
        if(!Is_prime[i]){
            if(ju(i)){
                prime[num++] = i;
                for(int j=2*i;j<=maxn;j+=i){
                    Is_prime[j]=1;
                }
            }else continue;
        }
     }
}
int main()
{
    int n,ans=0;
    cin >> n;
    rep();
    for(int i=3;i<=n/2;i++){
        if(!Is_prime[i]&&!Is_prime[n-i])
            ans ++ ;
    }
    cout <<ans;
    return 0;
}

问题 E: XX要回家
题目描述
XX被无情的Y老板因为任务没完成而被开除了 心灰意冷的XX想以最快的速度回家 现在XX有以下几种途径可以移动(假设现在的位置为x):
1.向前走一步到达x+1
2.向后走一步到达x-1
3.想到冷酷无情的Y老板而爆发跑到到2*x;
现在简化XX与家的位置 假设XX的位置为x(x<10000) 家的位置为y(y<10000) 试计算最快到家的方式(三种途径耗时相同)

输入
5 17

输出
4

样例输入
1 10000

样例输出
16

提示
例1的 5 17 可以通过-1,*2,2,+1或者2,-1,*2,-1的方式到达

超经典的**BFS**入门题,了解一下BFS是什么就可以做出来,
为了不让同学们百度而改了题面,XX真的是煞费苦心呀

原题:Catch That Cow–POJ3278
原题链接:http://poj.org/problem?id=3278

#include<iostream>
#include<queue>
using namespace std;
int a[10010];
int visited[10010];
struct Node
{
    int x,step;
    Node(int xx,int ss):x(xx),step(ss) { }
};
queue<Node> q;
int main()
{
    int a,b;
    cin >> a >> b;
    q.push(Node(a,0));
    visited[a]=1;
    while(!q.empty()){
        Node s = q.front();
        if(s.x==b){
            cout << s.step << endl;
            return 0;
        }
        else{
            if(s.x-1>=0&&!visited[s.x-1]){
                q.push(Node(s.x-1,s.step+1));
                visited[s.x-1]=1;
            }
            if(s.x+1<=b&&!visited[s.x+1]){
                q.push(Node(s.x+1,s.step+1));
                visited[s.x+1]=1;
            }
            if(s.x*2<=b&&!visited[s.x*2]){
                q.push(Node(s.x*2,s.step+1));
                visited[s.x*2]=1;
            }
        }
        q.pop();
    }
    return 0;
}

问题 F: XX的任务
题目描述
最近Y老板给XX布置了一项轻(fu)松(za)的任务 然而XX的间接性拖延症又双叒叕犯了 现在工程到了最后一天 XX不得不赶(肝)这项工程 还好XX想到了一种办法可以解决这项任务 请你来救救XX的拖延症吧

任务:给定工程的编号 输出对应的名字(用26个大写英文字母表示即可)

输入
输入一个数字n
输出
输出n所代表项目的名称

样例输入
1
2
26
27
28
424

样例输出
A
B
Z
AA
AB
PH

提示
进制

由于是从1~26所以不能直接转26进制,转换的过程中每一位都需要-1

递归解法

#include<iostream>
using namespace std;
void slove(int n)
{
    if(n<=0) return ;
    slove((n-1)/26);
    cout << (char)('A'+(n-1)%26);
}
int main()
{
    int n;
    while(cin >> n){
        slove(n);
        cout << endl;
    }
    return 0;
}

便于理解:

#include<iostream>
#include<stack>
using namespace std;
int main()
{
    stack<int> s;
    int n;
    while(cin >> n)
    {
        while(n)
            s.push((n-1)%26),n=(n-1)/26;
        while(!s.empty())
            cout << (char)('A'+s.top()),s.pop();
        cout << endl;
    }
    return 0;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值