浪在ACM11.2第三次训练赛

A.珠心算测试

题目描述

珠心算是一种通过在脑中模拟算盘变化来完成快速运算的一种计算技术。珠心算训练, 既能够开发智力,又能够为日常生活带来很多便利,因而在很多学校得到普及。 某学校的珠心算老师采用一种快速考察珠心算加法能力的测验方法。他随机生成一个正 整数集合,集合中的数各不相同,然后要求学生回答:其中有多少个数,恰好等于集合中另 外两个(不同的)数之和? 最近老师出了一些测验题,请你帮忙求出答案。

 

输入

输入共两行,第一行包含一个整数 n,表示测试题中给出的正整数个数。 
第二行有 n 个正整数,每两个正整数之间用一个空格隔开,表示测试题中给出的正整数。 

 

输出

输出共一行,包含一个整数,表示测验题答案。

 

样例输入

4
1 2 3 4

 

样例输出

2

 

提示

【样例说明】 
    由 1+2=3,1+3=4,故满足测试要求的答案为 2。注意,加数和被加数必须是集合中的 两个不同的数。 


【数据说明】 
     对于 100%的数据,3 ≤ n ≤ 100,测验题给出的正整数大小不超过 10,000。 

 

这个题,真的要坑我一年!这个题要去重!怎么个去重法呢,加法和只能有一个,比如1+3=4,2+2=4,和为4的所有,只能算一个。知道了这个坑点就好做很多了,可以用set去重,顺便排一下序,也可以手动去重。

首先,手动去重,从小到大排序,排序可以优化循环,因为各个加数也要不同(集合里的数都不同),所以,一前一后不同的数相加,然后,和从后往前找。

#include <bits/stdc++.h>
using namespace std;
int a[101],s,n,vis[101];
bool cmp(int a,int b)
{
    return a<b;
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    sort(a,a+n,cmp);//从小到大排序
    int Count=0;
    for(int i=0;i<=n-3;i++)
    {
        for(int j=i+1;j<=n-2;j++)
        {
             for(int k=n-1;k>j;k--)//从后往前,若大于和就--,
             {
                 if(a[i]+a[j]==a[k]&&!vis[k])
                 {
                     Count++;
                     vis[k]=1;
                 }
                 if(a[i]+a[j]>a[k])//小于和就break,从小到大排序,前面不可能有比a[k]大的了
                 {
                     break;
                 }
             }
        }
    }
    cout<<Count<<endl;
}

用set,把所有数放进去,如果和存在的话,就删除一下

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=10000+5;
set<int> num;
set<int> res;
int n,a[105],tmp;
int Count;
int main()
{
    cin>>n;
    for(int i=0;i<n;++i)
    {
        cin>>a[i];
        num.insert(a[i]);
    }
    for(int i=0;i<=n-2;++i)
    {
        for(int j=i+1;j<=n-1;++j)
        {
            int tmp=a[i]+a[j];
            set<int>::iterator it=num.find(tmp);
            if(it!=num.end())
            {
                num.erase(tmp);//在set中删除tmp
                Count++;
            }
        }
    }
    cout<<Count;
    return 0;
}

 

 

B.比例简化

 

题目描述

在社交媒体上,经常会看到针对某一个观点同意与否的民意调查以及结果。例如,对某 一观点表示支持的有 1498 人,反对的有 902 人,那么赞同与反对的比例可以简单的记为 1498:902。 不过,如果把调查结果就以这种方式呈现出来,大多数人肯定不会满意。因为这个比例 的数值太大,难以一眼看出它们的关系。对于上面这个例子,如果把比例记为 5:3,虽然与 真实结果有一定的误差,但依然能够较为准确地反映调查结果,同时也显得比较直观。 现给出支持人数 A,反对人数 B,以及一个上限 L,请你将 A 比 B 化简为 A’比 B’,要 求在 A’和 B’均不大于 L 且 A’和 B’互质(两个整数的最大公约数是 1)的前ᨀ下,A’/B’ ≥ A/B 且 A’/B’ - A/B 的值尽可能小。

 

输入

输入共一行,包含三个整数 A,B,L,每两个整数之间用一个空格隔开,分别表示支持 人数、反对人数以及上限。

 

输出

输出共一行,包含两个整数 A’,B’,中间用一个空格隔开,表示化简后的比例。

 

样例输入

1498 902 10 

 

样例输出

5 3

 

提示

【数据说明】 
     对于 100%的数据,1 ≤ A ≤ 1,000,000,1 ≤ B ≤ 1,000,000,1 ≤ L ≤ 100, A/B ≤ L。 

 

首先如果两个数的最简比值x,y 都小于L,的话,就两数除gcd就好了。如果不是的话,我就暴力枚举了(。・∀・)ノ。

因为题目中条件A’/B’ ≥ A/B 所以推出A'B>=B'A,还要A’/B’ - A/B尽可能小,所以每次枚举的时候,选最小的

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1000000+5;

int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}
int main()
{
    int x,y,L;
    cin>>x>>y>>L;
    int z=gcd(x,y);
    if(x/z<=L&&y/z<=L)
    {
         cout<<x/z<<' '<<y/z<<endl;
         return 0;
    }
    else
    {
        int nowx=maxn,nowy=1;
        for(int i=1;i<=L;i++)
        {
            for(int j=1;j<=L;j++)
            {
                if(i*y>=j*x)//这里不用考虑gcd为1,因为i j从小到大
                            //如果不互质的话,前面互质的(最简形式)已经比过了
                {
                    if(i*nowy<j*nowx)  //A'B'-AB尽可能小
                    {
                        nowx=i;
                        nowy=j;
                    }
                }
            }
        }
        cout<<nowx<<' '<<nowy<<endl;
    }
    return 0;
}

 

 

C.螺旋矩阵

 

题目描述

一个 n 行 n 列的螺旋矩阵可由如下方法生成: 从矩阵的左上角(第 1 行第 1 列)出发,初始时向右移动;如果前方是未曾经过的格子, 则继续前进,否则右转;重复上述操作直至经过矩阵中所有格子。 
根据经过顺序,在格子中 依次填入 1, 2, 3, ... , n 2 ,便构成了一个螺旋矩阵。 
下图是一个 n = 4 时的螺旋矩阵。 
 
现给出矩阵大小 n 以及 i 和 j,请你求出该矩阵中第 i 行第 j 列的数是多少。 

 

输入

输入共一行,包含三个整数 n,i,j,每两个整数之间用一个空格隔开,分别表示矩阵 大小、待求的数所在的行号和列号。

 

输出

输出共一行,包含一个整数,表示相应矩阵中第 i 行第 j 列的数。

 

样例输入

4 2 3 

 

样例输出

14

 

提示

【数据说明】 
    对于 50%的数据,1 ≤ n ≤ 100; 对于 100%的数据,1 ≤ n ≤ 30,000,1 ≤ i ≤ n,1 ≤ j ≤ n。 

 

为了找这个题的规律画了好多方阵(ง •_•)ง,

通过多画几个矩阵可以找到规律ㄟ( ▔, ▔ )ㄏ

第1行第j列 数为j,第n行第j列 数为3*n-j-1,第1列第i行 数为4*n-i-2,第n列第i行 数为n+i-1

第二层左边第一个数是4*n-4,既然知道了第二层的,那我们试试的第三层的最左边,得出4*(n-2)-4

可以这么看 每往里一层,就给方阵剥一层(突然血腥( ఠൠఠ )ノ)。那i,j就要分别-1,总层数n要-2

#include<bits/stdc++.h>
using namespace std;
int n;
int x,y;
int num;
int main()
{
    cin>>n>>x>>y;
    while(x!=1&&x!=n&&y!=1&&y!=n)
    {
        num+=4*n-4;  //每一层之间差4*n-4
        x-=1;
        y-=1;
        n-=2;
    }
    if(x==1)
    {
       num+=y;
    }
    else if(x==n)
    {
        num+=3*n-y-1;
    }
    else if(y==1)
    {
        num+=4*n-x-2;
    }
    else if(y==n)
    {
        num+=n+x-1;
    }

    cout<<num<<endl;
}

 

 

D.子矩阵

题目描述

一个 n 行 n 列的螺旋矩阵可由如下方法生成: 从矩阵的左上角(第 1 行第 1 列)出发,初始时向右移动;如果前方是未曾经过的格子, 则继续前进,否则右转;重复上述操作直至经过矩阵中所有格子。 
根据经过顺序,在格子中 依次填入 1, 2, 3, ... , n 2 ,便构成了一个螺旋矩阵。 
下图是一个 n = 4 时的螺旋矩阵。 
 
现给出矩阵大小 n 以及 i 和 j,请你求出该矩阵中第 i 行第 j 列的数是多少。 

 

输入

输入共一行,包含三个整数 n,i,j,每两个整数之间用一个空格隔开,分别表示矩阵 大小、待求的数所在的行号和列号。

 

输出

输出共一行,包含一个整数,表示相应矩阵中第 i 行第 j 列的数。

 

样例输入

4 2 3 

 

样例输出

14

 

提示

【数据说明】 
    对于 50%的数据,1 ≤ n ≤ 100; 对于 100%的数据,1 ≤ n ≤ 30,000,1 ≤ i ≤ n,1 ≤ j ≤ n。 

 

据说 状压DP,或者dfs+DP, 蒟蒻还没敢开始

 

 

 

E.计数问题

题目描述

试计算在区间 1 到 n 的所有整数中,数字 x(0 ≤ x ≤ 9)共出现了多少次?例如,在 1 到 11 中,即在 1、2、3、4、5、6、7、8、9、10、11 中,数字 1 出现了 4 次。

 

输入

输入共 1 行,包含 2 个整数 n、x,之间用一个空格隔开。

 

输出

输出共 1 行,包含一个整数,表示 x 出现的次数。

 

样例输入

11 1

 

样例输出

4

 

提示

【数据说明】 
     对于 100%的数据,1≤ n ≤ 1,000,000,0 ≤ x ≤ 9。 

 

这个,我就暴力枚举的,期待正解ing...

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1000000+5;
int a[maxn];
int main()
{
    int n,x;
    scanf("%d%d",&n,&x);
    int y,z;
    int num=0;
    for(int i=1;i<=n;i++)
    {
        y=i;
        while(y)
        {
            z=y%10;
            if(z==x)
            {
               num++;
            }
            y=y/10;
        }
    }
    cout<<num<<endl;
}

 

F.表达式求值

题目描述

给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值。

 

输入

输入仅有一行,为需要你计算的表达式,表达式中只包含数字、加法运算符“+”和乘 法运算符“*”,且没有括号,所有参与运算的数字均为 0 到 2^31 -1 之间的整数。 
输入数据保 证这一行只有 0~ 9、+、*这 12 种字符。 

 

输出

输出只有一行,包含一个整数,表示这个表达式的值。 
注意:当答案长度多于 4 位时, 请只输出最后 4 位,前导 0 不输出。 

 

样例输入

1+1*3+4 

 

样例输出

8

 

提示

样例 计算的结果为 8,直接输出 8。 


【数据范围】 
    对于 30%的数据,0≤表达式中加法运算符和乘法运算符的总数≤100; 
     对于 80%的数据,0≤表达式中加法运算符和乘法运算符的总数≤1000; 
    对于 100%的数据,0≤表达式中加法运算符和乘法运算符的总数≤100000。 

突然发现自己和振原同学,刘凯同学(是弟弟)的思路有很多重合之处,可能这就是菜菜与巨巨们之间莫名的心灵感应?(划掉),总体思路就是先算乘法后算加法,为什么?首先,乘法比加法的优先级高(废话( ̄▽ ̄)"),其次,乘法的连乘要特别注意。

连乘怎么写呢,比如a*b*c  可以把乘号后边的乘数b变成两乘数的乘积ab,然后a变成0,(利于加法去加,加0不会改变),然后ab与c相乘,同理变成 0,abc。然后数组里就变成0,0,abc,相加就阔以了(鼓掌(ง •_•)ง)

我使用的数组存数字,用字符存符号,首先第一个 是数字,然后就一直字符数字 字符数字...到字符为'\n'为止,所以可以先存一下第一个数字,然后再按字符数字的规律存。还有,加法和乘法都符合同余定理,记得随时mod(被坑了好久没爬出来,嘤嘤嘤? o(≧口≦)o) 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define Mod 1000
const int maxn=1000000+5;
char ch;
ll a[maxn];
int later;
int main()
{
    int num=0;
    int flag=0;
    cin>>a[num];  //第一个数字
    a[num]=a[num]%Mod;
    num++;
    while(1)
    {
        ch=getchar();//字符数字规律开始
        if(ch=='\n')
            break;
        cin>>a[num];
        a[num]%=Mod;
        //cout<<a[num-1]<<' '<<a[num]<<endl;
        if(ch=='*')//乘号
        {
            a[num]=a[num]*a[num-1]%Mod;//后面的乘数变成乘积
            //cout<<"num:"<<a[num]<<' ';
            a[num-1]=0;//前面的乘数化0
        }
        num++;
    }
    ll sum=0;
    for(int i=0;i<num;i++)
    {
        //cout<<a[i]<<endl;
        sum=(sum+a[i])%Mod;//求和
    }
    sum=sum%Mod;
    cout<<sum<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值