2018 3 15省赛训练

http://acm.ocrosoft.com/contest.php?cid=1034

NOIP2005普及组第2题 校门外的树

题意 给一段数轴,从0-n, 每次操作给一个l和r 删去l和r范围内的整数点,问最终还剩多少整数点

解 暴力即可。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
int main()
{
    int n,m;
    int x,y;
    int s[10010];
    while(cin>>n>>m)
    {
        memset(s,0,sizeof(s));
        for(int i=0;i<m;i++)
        {
            cin>>x>>y;
            for(int j=x;j<=y;j++)
                s[j]=1;
        }
        int res=0;
        for(int i=0;i<=n;i++)
        {
            if(!s[i])
                res++;
        }
        cout<<res<<endl;
    }
    return 0;
}



NOIP2005普及组第3题 采药

题意 采药,给一个背包容量,再给每个药的体积和价值,求最大价值。

解 简单的完全背包问题

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
int main()
{
    int t,m;
    int s[1010];
    int w[1010];
    int dp[1010];
    while(cin>>t>>m)
    {
        memset(dp,0,sizeof(dp));
        for(int i=0;i<m;i++)
        {
            cin>>s[i];
            cin>>w[i];
        }
        for(int i=0;i<m;i++)
        {
            for(int j=t;j>=s[i];j--)
                dp[j]=max(dp[j],dp[j-s[i]]+w[i]);
        }
        cout<<dp[t]<<endl;
    }
    return 0;
}


NOIP2005普及组第4题 循环

题意 给一个大数,求后k位的数字在该数不停的相乘时重复出现的循环节

解 直接找不现实,需要从低位向高位不断寻找该位的循环节,即在前i位的循环节的基础上寻找第i+1位的循环节,相乘即是前i+1位的循环节,本题需要注意的是最终答案也是大数。。。。

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int L=110000;
int l[11]={1,1,4,4,2,1,1,4,4,2};
int k;
void multiplyh(int x[], int y[], int z[]) {
    int up = 0;
    for (int ii = 1; ii <= k; ii++) {
        for (int j = 1; j <= k; j++)
        {
            z[ii + j - 1] += (x[j] * y[ii] + up) % 10;
            up = (x[j] * y[ii] + up) / 10;
        }
        up = 0;
    }
    for (int ii = 1; ii <= k; ii++) {
        z[ii + 1] += z[ii] / 10;
        z[ii] %= 10;
    }
}
void multiplyl(int x[], int yy, int z[]) {
    int up = 0;
    for (int ii = 1; ii <= k; ii++) {
        z[ii] = (x[ii] * yy + up) % 10;
        up = (x[ii] * yy + up) / 10;
    }
}
int main()
{
    string a;
    int b[205],c[205],d[205],now[205],last[205],ss[205];
     memset(last, 0, sizeof last);
    memset(b, 0, sizeof b); memset(now, 0, sizeof now);
    memset(d, 0, sizeof d); memset(c, 0, sizeof c); memset(ss, 0, sizeof ss);
    cin>>a;
    cin>>k;
    int n=a.size();
    int z=0;
    for(int i=n-1;i>=n-k;i--)
        c[++z]=a[i]-'0';
    for(int i=1;i<=k;i++)
        b[i]=c[i];
    for(int i=1;i<l[c[1]];i++)
    {
        memset(d,0,sizeof(d));
        multiplyh(b,c,d);
        for(int j=1;j<=k;j++)b[j]=d[j];
    }
    ss[1]=l[c[1]];
    for(int i=1;i<=k;i++)now[i]=b[i];
    for(int i=1;i<=k;i++)last[i]=now[i];
    int pos=2;
    int t=0;
    while(pos<=k)
    {
        for(int i=1;i<=k;i++)
        {
            b[i]=c[i];
        }
        t=0;
        while(t<11)
        {
            t++;
            memset(d,0,sizeof(d));
            multiplyh(b,now,d);
            for(int j=1;j<=k;j++)
            {
                b[j]=d[j];
            }
            if(b[pos]==c[pos])
            {
                break;
            }
            memset(d,0,sizeof(d));
            multiplyh(last,now,d);
            for(int j=1;j<=k;j++)
            {
                last[j]=d[j];
            }
        }
        if(t>=11){cout<<-1<<endl;return 0;}
        for(int j=1;j<=k;j++)now[j]=last[j];
        memset(d,0,sizeof(d));
        multiplyl(ss,t,d);
        for (int i = 1; i <= 100; i++)  ss[i] = d[i];
        pos++;
    }
    int flag = 0;
    for (int i = 100; i >= 1; i--) {
        if (ss[i]) flag = 1;
        if (flag) cout << ss[i];
    }
    cout<<endl;
    return 0;
}


2012_p1 质因数分解

题意 求一个数能由2个不同的质数相乘得到,求其中较大的质数

解 如果一个数能由2个不同的质数相乘得到,则不难想到该数只可能有4个因子,即1和其本身和另外2个质数,所以只要从该数的开根号开始向下遍历找到一个可以整除的数即可。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int main()
{
    int n;
    while(cin>>n)
    {
        for(int i=sqrt(n*1.0);i>1;i--)
        {
            if(n%i==0)
                cout<<n/i<<endl;
        }
    }
    return 0;
}


2012_p2 寻宝

见下博客:

http://blog.csdn.net/b_r_e_a_d/article/details/79597361


2012_p3 摆花

题意 n种花 每种花最多摆ai盆,一共需要摆m盆且从小到大的顺序,问有多少种摆法

解 一开始想到排列组合,但没想出来,于是想到dp,确实是dp,dp[i][j]表示前i种花中拿出j盆来摆的可能性 具体看代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,m;
    while(cin>>n>>m)
    {
        long long dp[211][211];
        memset(dp,0,sizeof(dp));
        long long a[211];
        for(int i=1;i<=n;i++)
            cin>>a[i];
        for(int i=0;i<=a[1]&&i<=m;i++)
            dp[1][i]=1;
        for(int i=2;i<=n;i++)
        {
 
                for(int k=0;k<=m;k++)
       {
           for(int j=0;j<=a[i]&&j<=k;j++)
            {
                    dp[i][k]=(dp[i-1][k-j]+dp[i][k])%1000007;
                }
            }
        }
        cout<<dp[n][m]%1000007<<endl;
    }
    return 0;
}


2012_p4 文化之旅

见https://my.csdn.net/imzxww

如果他写了的话。。


比赛安排

题意:2^n支队伍对打,每天每支队伍都要出场且2个队伍必须对打一次,求在2^n-1天里队伍安排如何,需要从小到大安排

解 简单穷举

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;;
int main()
{
    int n;
    while(cin>>n)
    {
        int da=pow(2.0,n)-1;
        int me=da+1;
        bool dp[70][70];
        bool vis[70];
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=da;i++)
        {
            int q=0;
            memset(vis,0,sizeof(vis));
            cout<<"<"<<i<<">";
            for(int j=1;j<=me;j++)
            {
               if(vis[j]==1)continue;
               vis[j]=1;
               for(int k=j+1;k<=me;k++)
               {
                   if(vis[k]==0&&dp[j][k]==0)
                   {
                       dp[j][k]=1;
                       vis[k]=1;
                       if(q++)cout<<",";
                       cout<<j<<"-"<<k;
                       break;
                   }
               }
            }
            cout<<endl;
        }
    }
    return 0;
}


上下火车

题意 火车从始发站(称为第1站)开出,在始发站上车的人数为a,然后到达第2站,在第2站有人上、下车,但上、下车的人数相同,因此在第2站开出时(即在到达第3站之前)车上的人数保持为a人。从第3站起(包括第3站)上、下车的人数有一定规律:上车的人数都是前两站上车人数之和,而下车人数等于上一站上车人数,一直到终点站的前一站(第n-1站),都满足此规律。现给出的条件是:共有N个车站,始发站上车的人数为a,最后一站下车的人数是m(全部下车)。试问x站开出时车上的人数是多少?

解 用纸算一算每一站的上车人数与净上车人数即可,与斐波那契数列有关

#include<cmath>
#include<cstdio>
#include<vector>
#include<iomanip>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long int 
LL up[10000];
LL down[10000];
LL ck[10000];
int main()
{
    LL a, n, m, x; 
    while (~scanf("%ld %ld %ld %ld", &a, &n, &m, &x))
    {
        memset(ck, 0, sizeof(ck));
        up[1] = a;
        down[1] = 0;
        ck[1] = a;
        bool flag = 0;
        for (LL i = 0; i <= m; i++)
        {
            up[2] = i;
            down[2] = i;
            ck[2] = ck[1];
            for (LL j = 3; j<n; j++)
            {
                up[j] = up[j - 1] + up[j - 2];
                down[j] = up[j - 1];
                ck[j] = ck[j - 1] + up[j - 2];
            }
            if (ck[n - 1] == m)
            {
                printf("%ld\n", ck[x]); 
                flag = 1; 
                break;
            }
        }
        if (!flag)
            printf("No answer.\n");
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值