第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛(部分)

20 篇文章 0 订阅
19 篇文章 0 订阅

A 跳台阶
有一个n级台阶的楼梯,小明一次可以向上跳1步,两步,甚至是n步,请问小明跳到n级台阶有多少种跳法?
分析:第一眼想到1 2 和2 1 算两种还是一种,算2种,然后就暴搜了一下,找出规律 2^(n-1)
另一种分析思路:
因为每一步只能往前跳,而且可以任意跳,所以,可以由第 0,1,..n-1 级跳到第 n 级台阶很容易就可以推出第 n 级台阶的方案数,就是前 0~n-1 级台阶方案数的总和。第 0 级是 1,第 1 级也是 1,第 2 级是 2,第 3 级是 4,。。。因此第 n(n>0)级台阶就是 2 的(n-1)次方。

/**
D:psd面试
题意:给一个字符串,求去掉最长回文子序列得到的串的长度。
思路: 题目所说的 是最长回文子序列,也就是改回文串是可以不连续的。
将所给的字符串反转,变成求两个字符串的LCS(最长公共子序列)问题。
dp[i][j] = dp[i-1][j-1]+1,两字符相等时
dp[i][j] = max(dp[i-1][j],dp[i][j-1]),不等时 (1<=i,j<=sz)
**/

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

const int N=1234+5;
int dp[N][N];
int main()
{
    string str;
    while(cin>>str)
    {
        int sz=str.size();
        for(int i=0; i<sz; i++)
        {
            if(str[i]>='A'&&str[i]<='Z')
                str[i]+=32;
        }
        string t=str;
        dp[0][0]=0;
        reverse(t.begin(),t.end());
        for(int i=1; i<=sz; i++)
        {
            for(int j=1; j<=sz; j++)
            {
                if(str[i-1]==t[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<<sz-dp[sz][sz]<<endl;
    }
    return 0;
}

F 等式
题意:给定n,求1/x + 1/y = 1/n (x<=y)的解数。(x、y、n均为正整数)
分析:1/x+1/y=1/n
化简得到 (n-x)*(n-y)=n*n
转化为求 n*n 小等于 n 的因子的个数,由于 n 达到 10^9,直接求太大。 将n进行分解,利用唯一分解定理
n = p1^e1*p2^e2*p3^e3*…pn^en. n的因子个数为(1+e1)(1+e2)(1+en),而x<=y,所以最后输出(ans+1)/2;

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

#define mem(a,n) memset(a,n,sizeof(a))
#define memc(a,b) memcpy(a,b,sizeof(b))
#define rep(i,a,n) for(int i=a;i<n;i++) ///[a,n)
#define pb push_back
#define IO ios::sync_with_stdio(false)
#define fre freopen("in.txt","r",stdin)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
const double PI=acos(-1.0);
const double E=2.718281828459045;
const double eps=1e-7;
const int INF=0x3f3f3f3f;
const int MOD=1e8+7;
const int N=1e5+5;
const ll maxn=1e6+5;
const int dir[4][2]= {-1,0,1,0,0,-1,0,1};
const ll inf=0x3f3f3f3f3f3f3f3f;

int prime[105];
int n;
void solve()
{
    int cnt=0;
    mem(prime,0);
    for(int i=2; i*i<=n; ++i)
    {
        if(n%i==0)
        {
            while(n%i==0)
            {
                prime[cnt]++;
                n/=i;
            }
            cnt++;
        }
    }
    if(n!=1)
    {
        prime[cnt]++;
        cnt++;
    }
    int ans=1;
    for(int i=0; i<cnt; i++)
        ans*=(2*prime[i]+1);
    printf("%d\n",(ans+1)/2);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        solve();
    }
    return 0;
}

G 旋转矩阵
景驰公司的试验车上面有一个奇怪的图案,这是一个n*m的矩阵,这辆车可以到处开,每次可以左旋右旋,小明想知道转完之后的图案是怎么样的
具体来说:有一个n*m的字符矩阵,只包含3种字符(‘+’‘-’,‘|’),通过一通乱旋之后变成什么样子?

分析:纯模拟
注意- 和 | 左旋90°和右旋90°的情况。

char str[N][N];
char op[1005];
int cnt;
int n,m;
char change(char ch)
{
    if(ch=='-') return '|';
    else if(ch=='|') return '-';
    else return ch;
}
void solve()
{
    if(cnt==0)
    {
        printf("%d %d\n",n,m);
        rep(i,0,n) puts(str[i]);
    }
    if(cnt==1)
    {
        printf("%d %d\n",m,n);
        for(int j=m-1; j>=0; j--)
        {
            for(int i=0; i<n; i++)
            {
                putchar(change(str[i][j]));
            }
            puts("");
        }
    }
    if(cnt==2)
    {
        printf("%d %d\n",n,m);
        for(int i=n-1; i>=0; i--)
        {
            for(int j=m-1; j>=0; j--)
                putchar(str[i][j]);
            puts("");
        }
    }
    if(cnt==3)
    {
        printf("%d %d\n",m,n);
        for(int j=0; j<m; j++)
        {
            for(int i=n-1; i>=0; i--)
            {
                putchar(change(str[i][j]));
            }
            puts("");
        }
    }
    puts("");
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        rep(i,0,n)
        {
            scanf("%s",str[i]);
        }
        scanf("%s",op);
        cnt=0;
        int len=strlen(op);
        rep(i,0,len)
        {
            if(op[i]=='L') cnt++;
            else cnt--;
            if(cnt<0) cnt+=4;
            cnt%=4;
        }
        //printf("cnt=%d\n",cnt);
        solve();
    }
    return 0;
}

J 强迫症的序列
小A是一个中度强迫症患者,每次做数组有关的题目都异常难受,他十分希望数组的每一个元素都一样大,这样子看起来才是最棒的,所以他决定通过一些操作把这个变成一个看起来不难受的数组,但他又想不要和之前的那个数组偏差那么大,所以他每次操作只给这个数组的其中n-1个元素加1,但是小A并不能很好的算出最优的解决方案,如果你能帮他解决这个问题,小A就能送你一个气球
分析:枚举了几种情况猜到了解法,没敲, 没转换思路
题目是给数列中的n-1个数+1,也相当于让最小值不动,其他值都-1一直减到与最小值相等。这是最优方案。

const int N=1e5+5;

int a[N];
int main()
{
    int T,n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        rep(i,0,n) scanf("%d",&a[i]);
        sort(a,a+n);
        int ans=0;
        for(int i=1;i<n;i++)
        {
            ans+=(a[i]-a[0]);
        }
        printf("%d %d\n",ans,ans+a[0]);
    }
    return 0;
}

K 密码
转化的规则是把字符串以n行锯齿形写出来,然后再按从左到右,从上到下读取,
即为真正的密码。如ABABCADCE以3行写出:
分析: 比赛时,自己采取的是找规律的,自认为找到了规律,但是WA了若干次, 可能简单一些的就是在二维数组中模拟吧
模拟:

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

#define mem(a,n) memset(a,n,sizeof(a))
#define memc(a,b) memcpy(a,b,sizeof(b))
#define rep(i,a,n) for(int i=a;i<n;i++) ///[a,n)
#define pb push_back
#define IO ios::sync_with_stdio(false)
#define fre freopen("in.txt","r",stdin)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
const double PI=acos(-1.0);
const double E=2.718281828459045;
const double eps=1e-7;
const int INF=0x3f3f3f3f;
const int MOD=1e8+7;
const int N=1e5+5;
const ll maxn=1e6+5;
const int dir[4][2]= {-1,0,1,0,0,-1,0,1};
const ll inf=0x3f3f3f3f3f3f3f3f;

vector<char>vec[N];
string str;
int main()
{
    int T,n;
    cin>>T;
    while(T--)
    {
        cin>>n>>str;
        rep(i,0,n) vec[i].clear();
        int sz=str.size();
        if(n==1||n==sz)
        {
            cout<<str<<endl;
            continue;
        }
        bool flag=1;
        int xb=-1;
        rep(i,0,sz)
        {
            if(flag) xb++;
            else xb--;
            vec[xb].pb(str[i]);
            if(i&&(!xb||xb==n-1)) flag^=1;
        }
        rep(i,0,n)
        {
            for(int j=0;j<(int)vec[i].size();j++)
                cout<<vec[i][j];
        }
        cout<<endl;
    }
    return 0;
}

规律:

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

string str;
int main()
{
    int T,n;
    cin>>T;
    while(T--)
    {
        cin>>n>>str;
        int sz=str.size();
        if(n==1||sz==n)
        {
            cout<<str<<endl;
            continue;
        }
        for(int i=1;i<=n;i++)
        {
            int xb=i-1;
            if(i==1||i==n)
            {
                while(xb<sz)
                {
                    putchar(str[xb]);
                    xb+=2*(n-1);
                }
            }
            else
            {
                bool flag=1;
                while(xb<sz)
                {
                    putchar(str[xb]);
                    if(flag) xb+=2*(n-i);
                    else xb+=2*(i-1);
                    flag^=1;
                }
            }
        }
        cout<<endl;
    }
    return 0;
}

L 用来作弊的药水
比较x^a与y^b是否相等。 1<=x,y,a,b<=10^9
分析:
1.因为数值范围比较大,结合题意容易想到取对数,但是比较时的eps不能太小,最多1e-5 ,不知道原因
比较气的是我就是精度爆炸中的一个, 取的1e-7,改一个数字就过了

另外,还可以
2.枚举几个素数进行取模快速幂求解;或者快速幂哈希几次,只要每次都相等 判断错误的概率几乎为0(来自学长题解)
3.分解质因数然后判断每个质因数的数量是否相等

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

#define mem(a,n) memset(a,n,sizeof(a))
#define memc(a,b) memcpy(a,b,sizeof(b))
#define rep(i,a,n) for(int i=a;i<n;i++) ///[a,n)
#define pb push_back
#define IO ios::sync_with_stdio(false)
#define fre freopen("in.txt","r",stdin)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
const double PI=acos(-1.0);
const double E=2.718281828459045;
const double eps=1e-3;
const int INF=0x3f3f3f3f;
const int MOD=1e8+7;
const int N=1234+5;
const ll maxn=1e6+5;
const int dir[4][2]= {-1,0,1,0,0,-1,0,1};
const ll inf=0x3f3f3f3f3f3f3f3f;

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        double x,a,y,b;
        scanf("%lf %lf %lf %lf",&x,&a,&y,&b);
        double tmp1=1.0*a*log10(x);
        double tmp2=1.0*b*log10(y);
        if(fabs(tmp1-tmp2)<eps) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
ll pow_mod(ll a,ll b,ll mod)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ans;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        ll x,y,a,b;
        cin>>x>>a>>y>>b;
        bool flag=0;
        for(int i=0;i<100;i++)
        {
            ll mod=rand()+1;
            ll tmp1=pow_mod(x,a,mod);
            ll tmp2=pow_mod(y,b,mod);
            if(tmp1!=tmp2)
            {
                flag=1;
                break;
            }
        }
        if(flag) cout<<"No"<<endl;
        else cout<<"Yes"<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值