2021计算智能期末复习

题1:18005 It is not ugly number

题目描述

18005 It is not ugly number
时间限制:2000MS 代码长度限制:10KB
提交次数:0 通过次数:0

题型: 编程题 语言: G++;GCC
Description
Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence1, 2, 3, 4, 5, 6, 8, 9, 10, 12, …shows the
first 10 ugly numbers. By convention, 1 is included. Then, here are the first 10 Not ugly numbers:7, 11, 13, 14, 17, 19,
21, 22, 23, 26. Given the integer n, write a program to find and print the n’th Not ugly number.

输入格式
First line is T(T<=10000), the number of cases.
The T lines following. Each line of the input contains a positive integer n (n <= 100000000).

输出格式
For each case, output the n’th Not ugly number .

输入样例
3
1
2
9

输出样例
7
11
23

解题思路

本题采用的是构造法(即用2、3、5轮流再乘2、3、5这样得到的数因子必然全部都是2、3、5)求丑数,然后用丑数在前100000000中选出非丑数的即可。选的方法是根据当前输入的数来确定,比如输入的是8,那么这8个里面要么都是丑数,要么有丑数也有非丑数,而非丑数+丑数的数量=当前输入的数来得到相关的数。
注意,这个方法是有缺陷的,就是必须先知道我们需要几个丑数,才能得到相应的答案

AC代码

#include <iostream>
#include <algorithm>
#include <utility>

using namespace std;

const int M=1000000+5;
const int N=100000000+5;
pair <long long ,int> p[M];
long long ans[M];
long long pans[N];

void solve()
{
    int b[3]={2,3,5};
    /*先找丑数*/
    int p1=3,p2=3,p3=1;
    /*p1是指向ans数组的下标,p2是指向pair扩展出来新节点的pair数组的下标,p3是指向当前需要扩展节点的pair数组下表*/
    for(int k=0;k<3;k++)
    {
        p[k+1].first=p[k+1].second=ans[k+1]=b[k];/*初始化*/
    }
    while(p1<=3300)
    {
        for(int k=0;k<3;k++)
        {
            if(p[p3].second>b[k])/*如果当前被扩展节点的因子大于了当前要乘的因子*/
            {
                continue;
            }
            else
            {
                ans[p1++]=p[p2++].first;
                if(p1>=3300)
                {
                    break;
                }
                p[p2].first=p[p3].first*b[k];
                p[p2].second=b[k];
            }
        }
        p3++;/*扩展结束,出队*/
    }
}

void GetAns()
{
    /*双指针,p1指向ans,p2指向pans*/
    int num=2;/*从二开始打表*/
    int p1=1,p2=1;
    while(p2<=N)
    {
        if(num==ans[p1])/*如果当前枚举到的数是丑数,就跳过,不加入答案数组*/
        {
            num++,p1++;
        }
        else/*否则,加入答案数组*/
        {
            pans[p2++]=num++;
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    p[0].first=1;p[0].second=1;
    solve();
    sort(ans,ans+3300);
    GetAns();
    int t;cin>>t;
    while(t--)
    {
        int n;cin>>n;
        cout<<pans[n]<<'\n';
    }
    return 0;
}

题2:18443 除法等式

题目描述

Description
输入正整数n,按从小到大的顺序输出所有形如abcde/fghij=n的表达式,其中aj各代表09中的一个数字
除了0可以重复外,其它数字不能重复,2<=n<=90000。

输入格式
多case,每行一个数字,最后一个数字是0

输出格式
除了最后一行0不用处理,
其它每个case,按被除数由小到大输出所有满足等式的情况
注:如果没有满足条件的等式,该case结束后,也需要输出一个空行

两个case之间用一个空行分隔

输入样例
44
666
6666
20000
0

输出样例
00176/00004=44
00308/00007=44
00352/00008=44
00572/00013=44
00704/00016=44
00792/00018=44
00836/00019=44
01056/00024=44
01408/00032=44
01584/00036=44
01628/00037=44
01672/00038=44
01760/00040=44
01892/00043=44
01980/00045=44
02068/00047=44
02156/00049=44
02376/00054=44
02948/00067=44
03080/00070=44
03168/00072=44
03256/00074=44
03520/00080=44
03564/00081=44
03740/00085=44
04180/00095=44
04268/00097=44
04312/00098=44
04620/00105=44
04752/00108=44
05720/00130=44
05896/00134=44
05984/00136=44
06028/00137=44
06072/00138=44
06380/00145=44
06908/00157=44
07040/00160=44
07392/00168=44
07920/00180=44
08360/00190=44
08536/00194=44
08976/00204=44
09108/00207=44
09460/00215=44
09504/00216=44
09548/00217=44
10560/00240=44
10780/00245=44
13068/00297=44
14080/00320=44
15268/00347=44
15840/00360=44
16280/00370=44
16720/00380=44
16940/00385=44
17600/00400=44
17820/00405=44
17952/00408=44
18700/00425=44
18920/00430=44
19008/00432=44
19800/00450=44
20108/00457=44
20680/00470=44
20900/00475=44
21560/00490=44
21780/00495=44
23760/00540=44
26004/00591=44
27940/00635=44
29480/00670=44
30140/00685=44
30712/00698=44
30800/00700=44
31020/00705=44
31680/00720=44
31856/00724=44
31900/00725=44
32560/00740=44
35024/00796=44
35200/00800=44
35640/00810=44
35904/00816=44
37400/00850=44
40260/00915=44
40700/00925=44
41008/00932=44
41800/00950=44
42108/00957=44
42680/00970=44
43120/00980=44
45628/01037=44
45672/01038=44
46200/01050=44
47520/01080=44
47652/01083=44
57200/01300=44
58476/01329=44
58960/01340=44
59268/01347=44
59840/01360=44
60280/01370=44
60720/01380=44
60940/01385=44
63800/01450=44
65032/01478=44
67408/01532=44
67892/01543=44
69080/01570=44
69432/01578=44
70048/01592=44
70400/01600=44
72380/01645=44
73920/01680=44
74052/01683=44
79200/01800=44
79420/01805=44
83600/01900=44
84700/01925=44
85360/01940=44
89760/02040=44
90068/02047=44
90376/02054=44
91080/02070=44
91300/02075=44
91740/02085=44
94600/02150=44
95040/02160=44
95348/02167=44
95480/02170=44

27306/00041=666
41958/00063=666
43290/00065=666
52614/00079=666
53946/00081=666
63270/00095=666

20000/00001=20000
40000/00002=20000
60000/00003=20000
80000/00004=20000

提示
提示:6666没有找到满足条件的等式

解题思路

本题的思路可以是按照题目的意思来做,重要的是两个思路,一个思路是乘法的思路,利用除法可以变成乘法这一思路来简化运算,然后是标记数组的使用,来帮助我们编写check函数。
乘法的思路:题目的意思是给出c,求满足a/b=c的式子,那么也就是a=b*c,c是确定的,bc不定,可以通过枚举b来得到a,而且我们可以知道,b的最大值是98765(因为全排列只能得到这么大的数),所以也就是
枚举b(从1开始,直到98765),然后乘c,放进check函数里面去测试,如果可以就输出,不行就不输出。

AC代码

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

typedef long long ll;
const int M=98765;
int book[10];
bool check(ll n,ll m)
{
    memset(book,0,sizeof(book));
    int flag=1;
    while(n)
    {
        book[n%10]++;
        n/=10;
    }
    while(m)
    {
        book[m%10]++;
        m/=10;
    }
    for(int i=1;i<=9;i++)
    {
        if(book[i]>1)
        {
            flag=0;
            break;
        }
    }
    return flag;
}

int main()
{
    ll n;
    while(scanf("%lld",&n) && n)
    {
        ll i;
        for(i=1;i<=M;i++)
        {
            if(i*n>M)
            {
                break;
            }
            else if(check(i,i*n))
            {
                printf("%05lld/%05lld=%lld\n",i*n,i,n);
            }
        }
        printf("\n");
    }
    return 0;
}

题3:18107 校赛排名

题目描述

Description
校赛结束了,每一个参赛选手由3个数据项构成(通过题数,用时分钟数,姓名),排名按照通过题数排序
通过题数多的排前,同题数的,罚时少的排前。如果题数相同,罚时也相同,而按数据读取的先后排。
给你N个参赛选手的数据,按排序先后,输出姓名

输入格式
第一个数为N,(N<=500000)
此后,每行一个参赛选手的数据,通过题数,用时分钟数,姓名,前两者为整型数,姓名为字符串(不多于20个字符)

输出格式
姓名排名

输入样例
4
3 5 Jon
5 100 Smith
3 5 Tom
6 95 Hel

输出样例
Hel
Smith
Jon
Tom

提示
由于有500000个数据,输入和输出务必使用scanf和printf

作者 admin

解题思路

本题的思路主要是根据交题数据的AC数和罚时来对各个队伍进行排序,所以主要考察的时sort中cmp的重载这个知识点。
这里复习以下cmp重载的用法
对于sort而言,其默认是按照从小到大的排序手法,那么编写比较函数的时候,就是当bool值为true的时候,就实行交换,如果是false的时候就不交换。
那么就可以理解成,在标志量被比较的时候的,使用大于号,那么就是越大的就会在越前面,使用小于号,越小的就会在越前面.

AC代码

vector存储法

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

struct data
{
    char name[20];
    int num;
    int time;
};


bool cmp(struct data a,struct data b)
{
    if(a.num>b.num)
    {
        return true;
    }
    else if(a.num==b.num && a.time < b.time)
    {
        return true;
    }
    else
    {
        return false;
    }
}


int main()
{
    vector <struct data> d;
    int n;scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        struct data temp;
        scanf("%d%d%s",&temp.num,&temp.time,temp.name);
        d.push_back(temp);
    }
    stable_sort(d.begin(),d.end(),cmp);
    for(int i=0;i<n;i++)
    {
        printf("%s\n",d[i].name);
    }
    return 0;
}
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdio>
using namespace std;

struct data
{
    char name[21];
    int time;
    int num;/*通过题数*/
};
bool cmp(struct data a,struct data b)
{
    if(a.num!=b.num)
    {
        return a.num>b.num;
    }
    else
    {
        return a.time<b.time;
    }
}

int main()
{
    vector <struct data> a;
    int n;scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        struct data temp;
        scanf("%d%d%s",&temp.num,&temp.time,temp.name);
        a.push_back(temp);
    }
    stable_sort(a.begin(),a.end(),cmp);
    for(int i=0;i<n;i++)
    {
        printf("%s\n",a[i].name);
    }
    return 0;
}
#include <iostream>
#include <algorithm>
#include <cstdio>

using namespace std;
const int M=500000+5;
struct data
{
    char name[21];
    int time;
    int num;
};
struct data a[M];
bool cmp(struct data a,struct data b)
{
    if(a.num!=b.num)
    {
        return a.num>b.num;
    }
    else
    {
        return a.time<b.time;
    }
}

int main()
{
    int n;scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d%s",&a[i].num,&a[i].time,a[i].name);
    }
    stable_sort(a,a+n,cmp);
    for(int i=0;i<n;i++)
    {
        printf("%s\n",a[i].name);
    }
    return 0;
}

题4:18290 校赛排名2

题目描述

Description
下面是校赛的排名规则:
比赛期间,提交代码后,系统会返回正确或错误等结果。最后的获胜者为正确解答题目最多,如果同题数则总用时最少的队伍。
每道试题的时间花费将从竞赛开始到试题提交并且被判定为正确为止,其间每一次提交运行结果被判错误的话将被加罚20分钟时间,
未正确解答的试题不记时,如果已经返回正确的题目再重复提交则不影响结果。
例如:A、B两队都正确完成两道题目,其中A队提交这两题的时间分别是比赛开始后60分钟和165分钟,B队为80分钟和130分钟,
但B队第一个题提交了2次才通过。这样A队的总用时为60+165=225而B队为(80+20)+130=230,所以A队以总用时少而获胜。
现在给出裁判机上面所有队伍的提交时间(分钟数)和返回结果,需要你编程输出当前比赛的排行榜。

注:0题的队伍不需要输出

输入格式
每行一个评判结果,格式为:时间(第几分钟提交的)+半角空格+队名+半角空格+题号+半角空格+评判结果(0通过,其它为出错)

题号由大写A字符开始,第2题是B,依次类推,最多不超过15题
所有评判结果已经按时间排序好

输出格式
输出排名,一行一个,格式为队名+半角空格+通过题数+半角空格+罚时

注:0题的队伍不需要输出
测试数据中,没有同题且同罚时的情况

输入样例
2 abc A 4
5 abc B 0
6 def A 0
10 abc A 0
13 xyx A 4
20 def B 5

输出样例
abc 2 35
def 1 6

作者 admin

解题思路

本题是上题的一个变形,不过这个变形比较复杂,首先是数据是原始的,多了几个数据,评判结果,评判题号等,
同时这些结果不再是现成的了,都是动态变化的。而且每道题都有AC和其他情况,所以就需要一个数组来记录每一个队伍每一道题目的状态,这些把这些状态存储在数组里,这样才会得到相应的答案。用到了一些哈希查找的思想。

AC代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int M=100000+5;
struct data
{
    int pass;
    int time;
    char name[21];
    int acname[21];/*标记作用*/
    int fal[21];
};

struct data a[M];

bool cmp(struct data a,struct data b)
{
    if(a.pass==b.pass)//同题数罚时少靠前
    {
        return a.time<b.time;
    }
    else
    {
        return a.pass>b.pass;
    }
}

int main()
{
    int n=0;/*队伍的数量*/
    char curname[21],ac;
    int Min,ifpass;
    while(scanf("%d %s %c %d",&Min,curname,&ac,&ifpass)!=EOF)
    {
        int i;bool IsSub=false;
        for(i=0;i<n;i++)
        {
            if(strcmp(a[i].name,curname)==0)
            {
                IsSub=true;
                break;
            }
        }
        if(!IsSub)/*如果没交过题*/
        {
            strcpy(a[i].name,curname);
            i=n;n++;
            /*初始化*/
            memset(a[i].acname,0,sizeof(a[i].acname));
            memset(a[i].fal,0,sizeof(a[i].fal));
            a[i].pass=0;a[i].time=0;
        }
        if(ifpass==0 &&a[i].acname[ac-'A']!=1)/*通过,而且是之前没通过的题*/
        {
            a[i].pass++;
            a[i].acname[ac-'A']=1;
            a[i].time+=a[i].fal[ac-'A']*20+Min;
        }
        else if(ifpass!=0 && a[i].acname[ac-'A']!=1 )/*没过,而且之前也没过*/
        {
            /*那么就加罚时*/
            a[i].fal[ac-'A']++;
        }
    }
    stable_sort(a,a+n,cmp);
    for(int i=0;i<n;i++)
    {
        if(a[i].pass!=0)
        {
            cout<<a[i].name<<' '<<a[i].pass<<' '<<a[i].time<<'\n';
        }
    }
    return 0;
}

题5:18118 勇者斗恶龙

题目描述

Description
有n个头的恶龙,你希望雇一些骑士把它杀死(即砍掉所有头)。村里有m个骑士可以雇佣,一个能力值为x的骑士可以砍掉恶龙
一个直径不超过x的头,且需要支付x个金币。如何雇佣骑士才能砍掉恶龙的所有头,且需要支付的金币最少?注意,一个骑士只
能砍一个头(且不能被雇佣两次)

输入格式
多组数据,每组数据的第一行为正整数n和m(1<=n,m<=200000);以下n行每行为一个整数,即恶龙每个头的直径;以下m行每行为
一个整数,即每个骑士的能力。输入结束标志n=m=0;

输出格式
输出格式:每组数据,输出最少花费,无解输出"Loowater is doomed!"

输入样例
2 3
5
4
7
8
4
2 1
5
5
10
0 0

输出样例
11
Loowater is doomed!

解题思路

本题的思路就是先对龙数组和人数组进行排序,确保用尽可能小的能力值去解决龙即可,使用的sort函数。

AC代码

#include <iostream>
#include <algorithm>

using namespace std;

const int M=200000+5;
int a[M],b[M];

int main()
{
    ios::sync_with_stdio(false);
    int n,m;
    /*a是龙数组,b是人数组*/
    while(cin>>n>>m && n &&m)
    {
        int i,j;
        long long sum=0;
        for(i=0;i<n;i++)
        {
            cin>>a[i];
        }
        for(j=0;j<m;j++)
        {
            cin>>b[j];
        }
        sort(a,a+n);sort(b,b+m);
        for(i=0,j=0;j<m&&i<n;)
        {
            if(b[j]>=a[i])
            {
                sum+=b[j];
                i++;j++;
            }
            else
            {
                j++;
            }
        }
        if(i==n)
        {
            cout<<sum<<'\n';
        }
        else
        {
            cout<<"Loowater is doomed!"<<'\n';
        }
    }
    return 0;
}

题6:1079 三角形

题目描述

Description
著名的数学家毕达哥拉斯可能从来都不曾想过有人居然会问他这样的一个问题:给出一个整数,存在多少个直角三角形,
它的某一条边的长度等于这个整数,而且其他边的长度也是整数。既然毕达哥拉斯不可能预见到有计算机的出现,
如果他回答不出来,那谁又能责怪他呢?但是现在既然你有了计算机,那么回答不出来就说不过去了。

输入格式 第一行有一个整数n,代表有多少个数据(1<=n<=20)。接下来有n行,每行代表一个数据。一个数据就是一个整数ai(a<=i<=n,1<=ai<=100)。

输出格式
每个数据都必须有相应的输出。两个数据的输出之间有一个空行。
对于每一个数据,如果找不到解,则输出一个空行。如果找到解,就把符合条件的所有直角三角形输出。每个三角形占一行,输出该三角形的另外两条边,
必须先输出长边,然后一个逗号,再输出短边。两个三角形之间不能有空行,而且必须按照长边降序排列。

输入样例
2
20
12

输出样例
101,99
52,48
29,21
25,15
16,12

37,35
20,16
15,9
13,5

解题思路

本题的思路关键是对输入的边n进行分类讨论,n既可以是直角边,也可以是斜边。
(1)如果n是直角边那么就是说需要枚举另外一条直角边来得到斜边,或者是说用斜边得到直角边,根据这个思路可以得到我们想要的结果。
首先我们假设n是直角边,a是直角边,c是斜边。那么就有** cc=nn+aa **
也就是** n
n=cc-aa **,设c-a=i那么就有a=(nn-ii)/(2i),那么对于c就是c=(nn+ii)/(2i)
这样就可以把三条边都枚举出来了,那么根据我们知道的,i是cc-aa的因子,也就是nn的因子,那么也就是i的范围是1-nn,这个范围内进行枚举即可。那么在这里需要保证几个条件来确保我们答案的稳定性。首先是a、c都要是正整数,然后i是n*n的因子。
(2)如果是n是斜边的话,那么就只需要双重循环枚举i,j验证勾股定理即可

AC代码

#include <iostream>
#include <cstdio>
using namespace std;

void solve(int n)
{
    bool IsFind=false;
    int i,j;
    for(i=1;i<=n*n;i++)
    {
        if((n*n)%i==0 && (n*n-i*i)/(2*i)>0 && ((n*n-i*i)/i)%2==0)
        {
            IsFind=true;
            cout<<(n*n+i*i)/(2*i)<<','<<(n*n-i*i)/(2*i)<<'\n';
        }
    }
    for(i=1;i<n;i++)
    {
        for(j=i;j<n;j++)
        {
            if(i*i+j*j==n*n)
            {
                IsFind=true;
                cout<<j<<','<<i<<'\n';
            }
        }
    }
    if(!IsFind)
    {
        cout<<'\n';
    }
}

int main()
{
    ios::sync_with_stdio(false);
    int t;cin>>t;
    while(t--)
    {
        int n;cin>>n;
        solve(n);
        cout<<'\n';
    }
    return 0;
}

题7:18444 分数拆分

题目描述

Description
输入正整数k(k<=1000),将1/k变为不少于2项,但不多于3项的1/(xi)之和,xi为正整数,且i表示序号

注:请使用long long

输入格式
多case,一行一个整数k

最后一行是0

输出格式
对每一个case,按等式最右边一项分母,由小到大排序输出满足条件的等式,最右边一项分母相同,则按最右边第二项,依次类推

每一个case完成后,输出一个空行(没有满足的等式时,也要输出该空行)

输入样例
2
3
4
0

输出样例
1/2=1/6+1/3
1/2=1/42+1/7+1/3
1/2=1/24+1/8+1/3
1/2=1/18+1/9+1/3
1/2=1/15+1/10+1/3
1/2=1/12+1/12+1/3
1/2=1/4+1/4
1/2=1/20+1/5+1/4
1/2=1/12+1/6+1/4
1/2=1/8+1/8+1/4
1/2=1/10+1/5+1/5
1/2=1/6+1/6+1/6

1/3=1/12+1/4
1/3=1/156+1/13+1/4
1/3=1/84+1/14+1/4
1/3=1/60+1/15+1/4
1/3=1/48+1/16+1/4
1/3=1/36+1/18+1/4
1/3=1/30+1/20+1/4
1/3=1/28+1/21+1/4
1/3=1/24+1/24+1/4
1/3=1/120+1/8+1/5
1/3=1/45+1/9+1/5
1/3=1/30+1/10+1/5
1/3=1/20+1/12+1/5
1/3=1/15+1/15+1/5
1/3=1/6+1/6
1/3=1/42+1/7+1/6
1/3=1/24+1/8+1/6
1/3=1/18+1/9+1/6
1/3=1/15+1/10+1/6
1/3=1/12+1/12+1/6
1/3=1/21+1/7+1/7
1/3=1/12+1/8+1/8
1/3=1/9+1/9+1/9

1/4=1/20+1/5
1/4=1/420+1/21+1/5
1/4=1/220+1/22+1/5
1/4=1/120+1/24+1/5
1/4=1/100+1/25+1/5
1/4=1/70+1/28+1/5
1/4=1/60+1/30+1/5
1/4=1/45+1/36+1/5
1/4=1/40+1/40+1/5
1/4=1/12+1/6
1/4=1/156+1/13+1/6
1/4=1/84+1/14+1/6
1/4=1/60+1/15+1/6
1/4=1/48+1/16+1/6
1/4=1/36+1/18+1/6
1/4=1/30+1/20+1/6
1/4=1/28+1/21+1/6
1/4=1/24+1/24+1/6
1/4=1/140+1/10+1/7
1/4=1/42+1/12+1/7
1/4=1/28+1/14+1/7
1/4=1/8+1/8
1/4=1/72+1/9+1/8
1/4=1/40+1/10+1/8
1/4=1/24+1/12+1/8
1/4=1/16+1/16+1/8
1/4=1/36+1/9+1/9
1/4=1/18+1/12+1/9
1/4=1/20+1/10+1/10
1/4=1/15+1/12+1/10
1/4=1/12+1/12+1/12

作者 admin

解题思路

本题仍然是一个简单的数学,对原式进行变换后即可得到我们想要的结论。

AC代码

#include <iostream>

using namespace std;

typedef long long ll;

void solve(ll k)
{
    ll i,j;
    for(i=k+1;i<=3*k;i++)
    {
        if((i*k)%(i-k)==0 && i<=(i*k)/(i-k))
        {
            cout<<"1/"<<k<<'='<<"1/"<<(i*k)/(i-k)<<'+'<<"1/"<<i<<'\n';
        }
        double k1=(i*k)/(i-k);
        for(j=k1+1;j<=2*k1+2;j++)
        {
            if(j<i || (i*j-k*i-k*j)<=0)
            {
                continue;
            }
            else if((k*i*j)%(i*j-k*i-k*j)==0 && (k*i*j)/(i*j-k*i-k*j)>=j)
            {
                cout<<"1/"<<k<<'='<<"1/"<<(k*i*j)/(i*j-k*i-k*j)<<'+'<<"1/"<<j<<'+'<<"1/"<<i<<'\n';
            }
        }
    }
    cout<<'\n';
}

int main()
{
    ios::sync_with_stdio(false);
    ll n;cin>>n;
    while(n!=0)
    {
        if(n==0)
        {
            break;
        }
        solve(n);
        cin>>n;
    }
    return 0;
}

题8:8623 龙龙

题目描述

在比赛的时候,1Y(1 次AC)是很值得高兴的事情。但很多大牛总会因为很弱智的错误先WA 一次,再AC。
而很多时候,这点罚时的差距使得他们与金牌无缘。弱智错误系列中最显著的就是忘记加龙龙。

龙龙外国人叫它作long long,表示64位整数,输入与输出64位整数则可以使用例如
scanf("%lld", &a)与printf("%lld", a)的形式完成。很多图论和动态规划的题目中,
虽然题目说最后输出的答案是32 位的整数,但中间计算的过程有时会超过int,这时我们就要使用龙龙了。

可惜的是,很多同学刚开始学写程序都是用VC的,在VC上是无法使用long long的,我们要用__int64
代替,输入与输出64位整数则可以使用例如scanf("%I64d", &a)与printf("%I64d", a)的形式完成。

但是提交上OJ 的时候,如果使用GCC或G++,都只支持long long,我们在提交时又得按照上边的改回来(的确挺麻烦,窘)。
为了让知道龙龙的同学们记得使用龙龙,不知道的学习使用龙龙,下边有个很简单的函数,希望大家
求出它的返回值:

long long H(int n){
long long res = 0;
int i;
for(i = 1; i <= n; i=i+1 ){
res = (res + n/i);
}
return res;
}

不过直接使用这个函数是会超时的,必须改造这个函数,当然这一定难不到未来的编程高手–你

输入格式
第一行是数字T(T<=1021)表示case数,接下来T 行,每行一个整数n,n是一个32 位整数(保证可以由int 表示)。

输出格式
函数返回值。

输入样例
2
5
10

输出样例
10
27

提示

解题思路

本题的思路关键是考虑产生的数,数是怎么产生的,我们可以知道整数在相除(int下)不会得到浮点数,因此求得的数都是若干个整数相加的来的。比如说我们以100举例,100/100=1,100/99=1…100/50=2…100/33=3…怎么样,是不是有点眉目了,也就是说:
从(n/i)到(n/i+1)之间会有若个干数的商都是(n/i),依照此结论进行编程
(实在不行就背吧。。代码也不长。。真的)

AC代码

#include <iostream>

using namespace std;

typedef long long ll;

ll H(ll n)
{
    ll i,a,b,ret=0;
    for(i=1,a=n;a>i;i++)
    {
        ret+=a;
        b=n/(i+1);
        ret+=(a-b)*i;
        a=b;
    }
    if(a==i)
    {
        ret+=a;
    }
    return ret;
}

int main()
{
    ios::sync_with_stdio(false);
    int t;cin>>t;
    while(t--)
    {
        ll n;cin>>n;
        ll ans=H(n);
        cout<<ans<<'\n';
    }
    return 0;
}

题9:1142 巡逻的士兵

题目描述

有N个士兵站成一队列, 现在需要选择几个士兵派去侦察。
为了选择合适的士兵, 多次进行如下操作: 如果队列超过三个士兵, 那么去除掉所有站立位置为奇数的士兵,
或者是去除掉所有站立位置为偶数的士兵。直到不超过三个战士,他们将被送去侦察。现要求统计按这样的方法,
总共可能有多少种不同的正好三个士兵去侦察的士兵组合方案。

注: 按上法得到少于三士兵的情况不统计。

1 <= N <= 2的32次方-1

输入格式
有多行(可能有上百行,尽量优化代码),每行一个数字N,最后一行是0

输出格式
对每一行的数字N,输出针对N的方案数

直到没有数字

输入样例
10
4
0

输出样例
2
0

解题思路

本题采用递归的做法,通过map数组来减少运算量,递归的具体分类是分奇数和偶数。

AC代码

#include <iostream>
#include <map>
#include <algorithm>

using namespace std;

typedef long long ll;
map <ll,ll> M;

ll F(ll n)
{
    if(n==3)
    {
        return 1;
    }
    if(n<3)
    {
        return 0;
    }
    else if(M[n]==0)
    {
        M[n]=F(n/2)+F((n+1)/2);
        return M[n];
    }
    else
    {
        return M[n];
    }

}

int main()
{
    ios::sync_with_stdio(false);
    ll n;
    while(cin>>n)
    {
        if(n==0)
        {
            break;
        }
        else
        {
            ll ans=F(n);
            cout<<ans<<'\n';
        }
    }
    return 0;
}

题10:18441 偷懒的士兵

题目描述

有N个士兵站成一队列, 现在需要选择几个士兵派去侦察。
为了选择合适的士兵, 多次进行如下操作: 如果队列超过三个士兵, 那么去除掉所有站立位置为奇数的士兵,
或者是去除掉所有站立位置为偶数的士兵。直到不超过三个战士,他们将被送去侦察。现有一个“聪明”的士兵,
经常通过选择站在合适的初始位置,成功避免被选中去侦察。这引起了陈教官的注意。陈教官希望你编写一个程序,
当给定士兵数之后,输出有多少个位置上的士兵是不可能被选中去巡逻的。

注: 按上法得到少于三士兵的情况不用去巡逻。

1 <= N <= 21亿

输入格式
有多行(可能有上百行,请尽量优化代码),每行一个数字N,最后一行是0

输出格式
对每一行的数字N,不可能被选中去巡逻的位置数

直到没有数字

输入样例
10
6
0

输出样例
4
0

作者 admin

AC代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <map>
using namespace std;

typedef long long ll;

map <ll ,ll >M;

ll F(ll n)
{
    if(n==3)
    {
        return 0;
    }
    if(n<3)
    {
        return n;
    }
    else if(M[n]==0)
    {
        M[n]=F(n/2)+F((n+1)/2);
        return M[n];
    }
    else
    {
        return M[n];
    }
}

int main()
{
    ios::sync_with_stdio(false);
    ll n;
    while(cin>>n)
    {
        if(n==0)
        {
            break;
        }
        else
        {
            ll ans=F(n);
            cout<<ans<<'\n';
        }
    }
    return 0;
}

题11:18442 偷懒的士兵2

题目描述

有N个士兵站成一队列, 现在需要选择几个士兵派去侦察。
为了选择合适的士兵, 多次进行如下操作: 如果队列超过三个士兵, 那么去除掉所有站立位置为奇数的士兵,
或者是去除掉所有站立位置为偶数的士兵。直到不超过三个战士,他们将被送去侦察。现有一个“聪明”的士兵,
经常通过选择站在合适的初始位置,成功避免被选中去侦察。这引起了陈教官的注意。陈教官希望你编写一个程序,
当给定士兵数之后,输出不可能被选中去巡逻的最少编号位置(如果不存在不可能被选中的位置,则输出0)。

注: 按上法得到少于三士兵的情况不用去巡逻。

1 <= N <= 100000

输入格式
有多行(不多于20行),每行一个数字N,最后一行是0

输出格式
对每一行的数字N,不可能被选中去巡逻的位置数

直到没有数字

输入样例
9
6
0

输出样例
2
0

作者 admin

思路分析

注意,本题和上面两道士兵系列的都很不一样,要输出的是最小的,不去巡逻的编号。那么这样就引起了一个质的变化

AC代码

#include <iostream>
#include <algorithm>

using namespace std;
typedef long long ll;
const int Lim=0x3f3f3f3f;
ll F(ll n,ll start,ll dis)/*start是编号*/
{
    if(n==3)
    {
        return 0;
    }
    if(n<3)
    {
        return start;
    }
    else
    {
        ll a=F((n+1)/2,start,dis*2);
        ll b=F(n/2,start+dis,dis*2);
        if(a==0)
        {
            return b;
        }
        else if(b==0)
        {
            return a;
        }
        else
        {
            return min(a,b);
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    ll n;
    while(cin>>n)
    {
        if(n==0)
        {
            break;
        }
        else
        {
            ll ans=F(n,1,1);
            cout<<ans<<'\n';
        }
    }
    return 0;
}

题12:18124 N皇后问题

题目描述

18124 N皇后问题
时间限制:5000MS 代码长度限制:10KB
提交次数:0 通过次数:0

题型: 编程题 语言: G++;GCC;VC
Description
有N*N的国际象棋棋盘,要求在上面放N个皇后,要求任意两个皇后不会互杀,有多少种不同的放法?

输入格式
每一个数为T,代表CASE的数量,T<=13
此后,每行一个数N(13>=N>0)

输出格式
每一个CASE,输出对应答案

输入样例
2
4
5

输出样例
2
10

AC代码

#include <iostream>

using namespace std;

const int M=100+5;
int c[M],cnt,n;

void Nqueue(int cur)
{
    if(cur==n+1)
    {
        cnt++;
        return ;/*回溯*/
    }
    int i,j;
    for(i=1;i<=n;i++)
    {
        c[cur]=i;bool ok=true;
        for(j=1;j<cur;j++)
        {
            if(c[j]==i || cur-c[cur]==j-c[j] || cur+c[cur]==j+c[j])
            {
                ok=false;
                break;
            }
        }
        if(ok)
        {
            Nqueue(cur+1);
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    int t;cin>>t;
    while(t--)
    {
        cnt=0;
        cin>>n;
        if(n<=0)
        {
            cout<<0<<'\n';
            continue;
        }
        Nqueue(1);
        cout<<cnt<<'\n';
    }
    return 0;
}

题13:18308 最长公共子序列

题目描述

给定两个字符串,请输出这两个字符串的最大公共子序列

输入格式
两行,一行一个字符串(不包括空格,Tab键),长度不超过1000

输出格式
输出最大公共子序列的长度

输入样例
abbca
aba

输出样例
3

作者 admin

思路分析

具体见我的动态规划入门

AC代码

#include <iostream>
#include <cstring>

using namespace std;
const int M=1000+5;
char a[M],b[M];
int dp[M][M];
int main()
{
    ios::sync_with_stdio(false);
    cin>>a>>b;
    int lena=strlen(a),lenb=strlen(b);
    for(int i=0;i<=lena;i++)
    {
        dp[i][0]=0;
    }
    for(int i=0;i<=lenb;i++)
    {
        dp[0][i]=0;
    }
    for(int i=1;i<=lena;i++)
    {
        for(int j=1;j<=lenb;j++)
        {
            if(a[i-1]==b[j-1])
            {
                dp[i][j]=dp[i-1][j-1]+1;
            }
            else
            {
                dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
            }
        }
    }
    cout<<dp[lena][lenb]<<'\n';
    return 0;
}

题14:8633 回文划分

题目描述

我们说一个字符串是回文串,那么意味着这个串从两边读起来的字母都是一样的。例如racecar是回文串,
然而fastcar则不是。
对一个串的划分意思是将一个串划分为若干个部分。例如,racecar可以划分为race 和car两部分。给出
一个串,要把这个串划分为若干个回文串,那么至少要把这个串划分为多少部分?
例如
'racecar’已经是回文串,划分为1 个部分即可(这个部分就是racecar)。
‘fastcar’ 需要被划分为七个部分 (‘f’, ‘a’, ‘s’, ‘t’, ‘c’, ‘a’, ‘r’)。根据回文串的定义,单个字母也是回文串。
‘aaadbccb’ 分成可以被分为三个回文串 (‘aaa’, ‘d’, ‘bccb’)。找不到更少的划分方法。

输入格式
输入的第一行是数字T,表示输入文件含有T个CASE。之后有T行,每行有一个长度不大于1000的字
符串,全部由小写字母组成,中间没有空格。

输出格式
对于每个CASE,输出一个数字,表示对该字符串的回文串最小划分。

输入样例
3
racecar
fastcar
aaadbccb

输出样例
1
7
3

提示

来源 PKKJ @ 07 GIS 1

作者 admin

AC代码

#include <iostream>
#include <cstring>
using namespace std;
const int M=1000+5;
char s[M];
int dp[M];
bool check(int l,int r)
{
    int i,j;
    for(i=l,j=r;i<r;i++,j--)
    {
        if(s[i]!=s[j])
        {
            return false;
        }
    }
    return true;
}

int main()
{
    ios::sync_with_stdio(false);
    int t;cin>>t;
    while(t--)
    {
        memset(s,0,sizeof(s));
        memset(dp,0,sizeof(dp));
        cin>>s;
        int lens=strlen(s);
        for(int i=0;i<lens;i++)
        {
            dp[i+1]=dp[i]+1;
            for(int j=0;j<i;j++)
            {
                if(check(j,i))
                {
                    dp[i+1]=min(dp[i+1],dp[j]+1);
           }
            }
        }
        cout<<dp[lens]<<'\n';
    }
    return 0;
}

由于走迷宫2比较简单,所以先做这道题的复习

题15:18440 走迷宫2

题目描述

Description
有一个N*M(N,M<=10)的格子迷宫,1代表该格子为墙,不能通过,0代表可以通过,人在迷宫中可以尝试上下左右四个方向移动。
另外,在迷宫中如果从左边走出迷宫会回到迷宫最右边一格(只要该格不是墙),行不变,同样,从右边走出迷宫会
回到迷宫最左边一格,向上走出迷宫会回到迷宫最下边一格,向下走出迷宫会回到迷宫最上边一格。
现在给定一个迷宫,以及起点和终点,问最少多少步可以走出迷宫。如果不能走出迷宫输出“die”。

输入格式
该程序为多CASE,第1行为CASE的数量
每一个CASE,第1行为两个数N(行)和M(列)
然后N行每行M个数,之后是起点坐标和终点坐标sc(行) sr(列) ec(行) er(列)

输出格式
如题

输入样例
2
4 3
011
010
110
110
0 0 3 2
2 2
01
10
0 0 1 1

输出样例
4
die

提示
第一个case,可以从(1,0)走到(1,2)

深搜广搜都可以,下面直接贴代码

AC代码

#include <iostream>
#include <cstring>
using namespace std;

const int M=15;
const int Min=0x3f3f3f3f;
int book[M][M];
char a[M][M];
//dfs
bool IsFind=false;
int targetx,targety,n,m,fi=Min;
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
/*要求最小值*/
void dfs(int x,int y,int step)
{
    if(x==targetx && y==targety)
    {
        IsFind=true;
        fi=min(fi,step);
        return ;/*backtrack*/
    }
    for(int k=0;k<4;k++)
    {
        int tx=x+dir[k][0];
        int ty=y+dir[k][1];
        if(tx<-1|| tx>n||ty<-1||ty>m)
        {
            continue;
        }
        if(tx==-1)
        {
            tx=n-1;
        }
        if(tx==n)
        {
            tx=0;
        }
        if(ty==-1)
        {
            ty=m-1;
        }
        if(ty==m)
        {
            ty=0;
        }
        if(book[tx][ty]==0 && a[tx][ty]=='0')
        {
            book[tx][ty]=1;
            dfs(tx,ty,step+1);
            book[tx][ty]=0;
        }
    }
    return ;
}

int main()
{
    ios::sync_with_stdio(false);
    int t;cin>>t;
    while(t--)
    {
        cin>>n>>m;
        memset(book,0,sizeof(book));
        memset(a,0,sizeof(a));
        IsFind=false;fi=Min;
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
        }
        int startx,starty;
        cin>>startx>>starty>>targetx>>targety;
        /*dfs*/
        book[startx][starty]=1;
        dfs(startx,starty,0);
        if(IsFind)
        {
            cout<<fi<<'\n';
        }
        else
        {
            cout<<"die"<<'\n';
        }
    }
    return 0;
}

bfs的代码

#include <iostream>
#include <cstring>
using namespace std;

const int M=15;
const int Min=0x3f3f3f3f;
int book[M][M];
char a[M][M];
const int N=1e5+5;
//bfs
bool IsFind=false;
int targetx,targety,n,m,fi=Min;
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
struct data
{
    int x;int y;
    int step;
};
struct data q[N];
/*要求最小值*/

int main()
{
    ios::sync_with_stdio(false);
    int t;cin>>t;
    while(t--)
    {
        cin>>n>>m;
        memset(book,0,sizeof(book));
        memset(a,0,sizeof(a));
        IsFind=false;fi=Min;
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
        }
        int startx,starty;
        cin>>startx>>starty>>targetx>>targety;
        int head=0,tail=0;
        q[tail].x=startx;
        q[tail].y=starty;
        q[tail].step=0;
        book[startx][starty]=1;
        tail++;
        while(head<tail)
        {
            if(q[head].x==targetx && q[head].y==targety)
            {
                IsFind=true;
                break;
            }
            for(int k=0;k<4;k++)
            {
                if(IsFind==true)
                {
                    break;
                }
                int tx=q[head].x+dir[k][0];
                int ty=q[head].y+dir[k][1];
                if(tx<-1||tx>n||ty<-1||ty>m)
                {
                    continue;
                }
                else
                {
                    if(tx==-1)
                    {
                        tx=n-1;
                    }
                    if(tx==n)
                    {
                        tx=0;
                    }
                    if(ty==-1)
                    {
                        ty=m-1;
                    }
                    if(ty==m)
                    {
                        ty=0;
                    }
                    if(book[tx][ty]==0 && a[tx][ty]=='0')
                    {
                        book[tx][ty]=1;
                        q[tail].x=tx;
                        q[tail].y=ty;
                        q[tail].step=q[head].step+1;
                        tail++;
                        if(tx==targetx && ty==targety)
                        {
                            IsFind=true;
                            break;
                        }
                    }
                }
            }
            head++;
            if(IsFind)
            {
                break;
            }
        }
        if(IsFind)
        {
            cout<<q[tail-1].step<<'\n';
        }
        else
        {
            cout<<"die"<<'\n';
        }
    }
    return 0;
}

麻烦的地方在于是否到达终点的这个判断 ,有很多次的。

题16:18276 走迷宫

题目描述

Description
有一个N*M的格子迷宫,1代表该格子为墙,不能通过,0代表可以通过,另外,在迷宫中
有一些传送门,走到传送门的入口即会自动被传送到传送门的出口(一次传送算1步)。人在迷宫中可以尝试
上下左右四个方向移动。现在给定一个迷宫和所有传送门的出入口,以及起点和终点,
问最少多少步可以走出迷宫。如果不能走出迷宫输出“die”。

输入格式
该程序为多CASE,第1行为CASE的数量
每一个CASE,第1行为两个数N(行)和M(列)
然后N行每行M个数
之后是一个数W,为传送门的数量
之后每行一个传送门的入口坐标c1(行),r1(列)和出口坐标c2,r2
之后是起点坐标和终点坐标sc(行) sr(列) ec(行) er(列)

注:传送门出入口和起点坐标和终点坐标不会出现在墙的位置
所有数字不超过100

输出格式
如题

输入样例
2
4 3
011
011
110
110
1
1 0 2 2
0 0 3 2
2 2
01
10
0
0 0 1 1

输出样例
3
die

作者 admin

解题思路

这道题一看数据范围,100*100那么肯定不能深搜了,深搜的话还要搞步数数组来剪枝,太麻烦了不如直接广搜
那么广搜的话和原来有什么区别呢,就是说要对扩张的头节点进行检测,如果头节点是传送门的话呢,那么这个头节点只能够扩列出一个节点出来,同时这个题的坑点在于,起点也有可能是传送点,如果不考虑这一点的话就会WA
下面是代码

AC代码

#include <iostream>
#include <cstring>
using namespace std;

const int M=100+5;

struct data
{
    int x;int y;int step;
};
char a[M][M];
int book[M][M],goin[M][2],out[M][2];
struct data q[M*M];
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int IsTp(int x,int y,int n)
{
    for(int i=0;i<n;i++)
    {
        if(x==goin[i][0] && y==goin[i][1])
        {
            return i;
        }
    }
    return -1;
}

int main()
{
    ios::sync_with_stdio(false);
    int t;cin>>t;
    while(t--)
    {
        memset(a,0,sizeof(a));
        memset(book,0,sizeof(book));
        memset(goin,0,sizeof(goin));
        memset(out,0,sizeof(out));
        memset(q,0,sizeof(q));
        int n,m;cin>>n>>m;
        bool IsFind=false;
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
        }
        int w;cin>>w;
        int startx,starty,targetx,targety;
        for(int i=0;i<w;i++)
        {
            for(int j=0;j<2;j++)
            {
                cin>>goin[i][j];
            }
            for(int j=0;j<2;j++)
            {
                cin>>out[i][j];
            }
        }
        cin>>startx>>starty>>targetx>>targety;
        int head=0,tail=0;
        q[tail].x=startx;
        q[tail].y=starty;
        q[tail].step=0;
        book[startx][starty]=1;
        tail++;
        /*首先检测起点是不是传送们*/
        if(IsTp(startx,starty,w)!=-1)
        {
            int pos=IsTp(startx,starty,w);
            int tx=out[pos][0];
            int ty=out[pos][1];
            q[tail].x=tx;q[tail].y=ty;
            book[tx][ty]=1;
            q[tail].step=q[head].step+1;
            tail++;head++;
            if(tx==targetx && ty==targety)
            {
                cout<<q[tail-1].step<<'\n';
                continue;
            }
        }
        while(head<tail)
        {
            if(q[head].x==targetx && q[head].y==targety)
            {
                IsFind=true;
                break;
            }
            /*传送门BFS,只有一次扩列*/
            if(IsTp(q[head].x,q[head].y,w)!=-1)
            {
                int pos=IsTp(q[head].x,q[head].y,w);
                int tx=out[pos][0],ty=out[pos][1];
                q[tail].x=tx;q[tail].y=ty;
                q[tail].step=q[head].step+1;
                book[tx][ty]=1;
                head++;tail++;
                if(tx==targetx && ty==targety)
                {
                    IsFind=true;
                    break;
                }
            }
            /*正常BFS*/
            for(int k=0;k<4;k++)
            {
                int tx=q[head].x+dir[k][0];
                int ty=q[head].y+dir[k][1];
                if(tx<0||tx>n-1||ty<0||ty>m-1)
                {
                    continue;
                }
               if(book[tx][ty]==0 && a[tx][ty]=='0')
               {
                   q[tail].x=tx;
                   q[tail].y=ty;
                   q[tail].step=q[head].step+1;
                   book[tx][ty]=1;
                   tail++;
                   if(tx==targetx && ty==targety)
                   {
                       IsFind=true;
                       break;
                   }
               }
            }
            head++;
            if(IsFind)
            {
                break;
            }
        }
      if(IsFind)
      {
          cout<<q[tail-1].step;
      }
      else
      {
          cout<<"die";
      }
      cout<<"\n";
    }
    return 0;
}

题17:8615 快乐

题目描述

Lian是一个喜欢看动画片的人,自从成为ACMer(ACM爱好者)之后,他又迷上了网上做题。做题让他快乐,不过这也是需要付出精力的!!
假设有n道题,Lian做出第i道题后,他可以获得的快乐指数将增加gethappy[i],而消耗掉的精力将是losspow[i]。
假设Lian初始的快乐指数为1,精力为2000。可以理解,如果他消耗完了所有的精力那他得到再多的快乐都没有用。
你的任务就是帮他计算他所能得到的最多的快乐指数,且最后他依然有多余的精力(即至少为1)。

输入格式
第一行输入一个整数n,表示有n道题。(n<=50)
第二行输入n个整数,表示gethappy[1]到gethappy[n]
第三行输入n个整数,表示losspow[1]到losspow[n]。

输出格式
一个整数,表示Lian所能获得的最大快乐指数。

输入样例
3
15 23 61
350 1301 1513

输出样例
77

来源 jiangju0

作者 admin

解题思路

就是个0-1背包问题,默写板子就完事了

AC代码

#include <iostream>

using namespace std;
const int M=2000+5;
const int N=50+5;
int dp[N][M];
int v[N],w[N];
int main()
{
    ios::sync_with_stdio(false);
    int n;cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>v[i];
    }
    for(int j=1;j<=n;j++)
    {
        cin>>w[j];
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1999;j>=0;j--)
        {
            if(j-w[i]<0)
            {
                dp[i][j]=dp[i-1][j];
            }
            else
            {
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
            }
        }
    }
    cout<<dp[n][1999]+1;
}

题18:18104 练习使用多case解题

题目描述

多CASE的问题在般有3种情形:(1)有一个数字开始表明CASE数目;(2)以特殊标志表示结束;(3)要求处理到最后一行。
现要求你在程序一次运行中,依次处理上述3种情况。

有三批测试数据,第1批测试数据,开头会以一个数字告之该批CASE数量,每一个CASE是两个正整数;
第1批测试数据结束后,紧接着是第2批数据,每一个CASE同样是两个正整数,第2批测试数据以两个0结束;
第2批测试数据结束后,紧接着是第3批数据,每一个CASE也是两个正整数,第3批测试数据一直到数据输入结束;

要求,每一个CASE,输出两数的最小公倍数
第1批测试数据处理完毕时,输出“group 1 done”
第2批测试数据处理完毕时,输出“group 2 done”
第3批测试数据处理完毕时,输出“group 3 done”

输入格式
有三批测试数据,第1批测试数据,开头会以一个数字告之该批CASE数量,每一个CASE是两个正整数(最大2的31次方);
第1批测试数据结束后,紧接着是第2批数据,每一个CASE同样是两个正整数,第2批测试数据以两个0结束;
第2批测试数据结束后,紧接着是第3批数据,每一个CASE也是两个正整数,第3批测试数据一直到数据输入结束;

输出格式
要求,每一个CASE,输出两数的最小公倍数
第1批测试数据处理完毕时,输出“group 1 done”
第2批测试数据处理完毕时,输出“group 2 done”
第3批测试数据处理完毕时,输出“group 3 done”

输入样例
2
6 10
5 12
8 16
12 18
8 4
0 0
4 5
4 6

输出样例
30
60
group 1 done
16
36
8
group 2 done
20
12
group 3 done

AC 代码

#include <cstdio>
#include <algorithm>

typedef long long ll;
using namespace std;

ll GetNum(ll a,ll b)
{
    return a*b /__gcd(a,b);
}

int main()
{
    ll n,m;
    int t;scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld",&n,&m);
        printf("%lld\n",GetNum(n,m));
    }
    printf("group 1 done\n");
    scanf("%lld%lld",&n,&m);
    while(n!=0&&m!=0)
    {
        printf("%lld\n",GetNum(n,m));
        scanf("%lld%lld",&n,&m);
    }
    printf("group 2 done\n");
    while(scanf("%lld%lld",&n,&m)!=EOF)
    {
        printf("%lld\n",GetNum(n,m));
    }
    printf("group 3 done\n");
    return 0;
}

本题坑点是long long

希望大家的计算智能都考100分!

5.29日复习

题1:丑数

这个题的思路感觉总是很混乱,要特别注意。

#include <iostream>
#include <algorithm>

using namespace std;

const int M=1000000+5;
const int N=100000000+5;
pair <long long ,int> p[M];
long long ans[M];
long long pans[N];

void solve()
{
    int b[3]={2,3,5};
    p[0].first=1,p[0].second=1;
    ans[0]=1;
    int p1=1,p2=0,p3=1;
    while(p1<=3300)/*当ans数组的元素少于3300个*/
    {
        for(int k=0;k<3;k++)
        {
            if(p[p2].second>b[k])
            {
                continue;
            }
            p[p3].first=p[p2].first*b[k];
            //cout<<p[p3].first<<endl;
            p[p3].second=b[k];
            ans[p1++]=p[p3++].first;
            if(p1>=3300)
            {
                break;
            }
        }
        p2++;
    }
}

void GetNum()
{
    int num=1,p1=0,p2=1;
    while(p2<=N)
    {
        if(num==ans[p1])
        {
            p1++;num++;
        }
        else
        {
            pans[p2++]=num++;
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    solve();
    sort(ans,ans+3300);
    GetNum();
    int t;cin>>t;
    while(t--)
    {
        int n;cin>>n;
        cout<<pans[n]<<endl;
    }
    return 0;
}

注:这是花了两个小时调bug搞出来的。。

题2:校赛排名2

这个也容易写错

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int M=500000+5;

struct data
{
    char name[21];
    int pass;
    int time;
    int acname[21];
    int fal[21];
};

struct data a[M];

bool cmp(struct data a,struct data b)
{
    if(a.pass==b.pass)
    {
        return a.time<b.time;
    }
    return a.pass>b.pass;
}

int main()
{
    int ifpass,Min,n=0;
    char id,name[21];
    while(scanf("%d %s %c %d",&Min,name,&id,&ifpass)!=EOF)
    {
        bool IsSub=false;
        int i=0;
        for(i=0;i<n;i++)
        {
            if(strcmp(name,a[i].name)==0)
            {
                IsSub=true;
                break;
            }
        }
        if(!IsSub)
        {
            i=n;n++;
            strcpy(a[i].name,name);
            memset(a[i].fal,0,sizeof(a[i].fal));
            memset(a[i].acname,0,sizeof(a[i].acname));
            a[i].pass=0;a[i].time=0;
        }
        if(ifpass==0 && a[i].acname[id-'A']!=1)
        {
            a[i].pass++;
            a[i].time+=Min+a[i].fal[id-'A']*20;
            a[i].acname[id-'A']=1;
        }
        else if(ifpass!=0 && a[i].acname[id-'A']!=1)
        {
            a[i].fal[id-'A']++;
        }
    }
    stable_sort(a,a+n,cmp);
    for(int i=0;i<n;i++)
    {
        if(a[i].pass==0)
        {
            break;
        }
        else
        {
            printf("%s %d %d\n",a[i].name,a[i].pass,a[i].time);
        }
    }
    return 0;
}

题3:分数拆分

这个题我感觉是我最不会写的了,最麻烦的一个,关键是那个取值范围都不知道为什么会这样

#include <iostream>

using namespace std;
typedef long long ll;
void solve()
{
    ll k;
    while(cin>>k && k)
    {
        ll i,j;
        for(i=k+1;i<=3*k;i++)
        {
            if((k*i)%(i-k)==0 && (k*i)/(i-k)>=i)
            {
                cout<<"1/"<<k<<"="<<"1/"<<(k*i)/(i-k)<<"+"<<"1/"<<i<<endl;
            }
            double k1=(k*i)/(i-k)+1;
            for(j=k1;j<=2*k1;j++)
            {
                if(j<i)
                {
                    continue;
                }
                else if((i*j*k)%(i*j-k*i-k*j)==0 && (i*j*k)/(i*j-k*i-k*j)>=j)
                {
                    cout<<"1/"<<k<<"="<<"1/"<<(i*j*k)/(i*j-k*i-k*j)<<"+"<<"1/"<<j<<"+"<<"1/"<<i<<endl;
                }
            }
        }
        cout<<endl;
    }
}

int main()
{
    ios::sync_with_stdio(false);
    solve();
    return 0;
}

坑点是那几个小于号的辅助判断条件,要注意好了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值