2017年浙江中医药大学大学生程序设计竞赛

题目链接



B 一生之敌



2*a*(a+1)^2 = b^2   因为要求b 所以先开个根号把b求出来 => b = sqrt(2*a)  * (a+1)
因为b是整数a也是整数, 而等式中出现了根号2,所以要变换一下把根号2去掉
令 sqrt(a) = sqrt(2*x) 其中2*x为整数 ,得到等式b = 2*x*(2*x*x+1) = 4*x*x*x + 2*x
二分x得到答案
其中因为n的范围在[1,1e19]内,而1e19是比long long 的范围大的
考虑了使用double 不过有精度误差,还用Java写了一次,还是错,,
结束看了别人的代码才想起来还有 unsigned long long 这一类型~

#include <iostream>
#include <string>
#include <string.h>
using namespace std;
#define ULL unsigned long long
ULL n;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%llu",&n);
        ULL l=0,r=1400000,mid;
        while(l<r){
            mid = (l+r)>>1;
            if(4*mid*mid*mid + 2*mid >= n) r = mid;
            else l = mid+1;
        }
        printf("%llu\n",2*r*(2*r*r+1));
    }
}




C 寻找zcmu

找到z后面第一个c再继续找c下面第一个m再找m下面第一个u,u的位置减去z的位置-3就是该zcmu连续要删除的字母个数

先从后往前预处理一下,求出每个z后面的第一个c,每个c后面的第一个m,每个m后面的第一个u,然后遍历一遍就得到答案了

#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
#define LL long long
const int N = 1e5 + 10;
int T,n,m,nt[N],len,ans;
char s[N];
void slove(char a,char b){
    for(int i = len-1,now = -1;i>=0;i--){
        if(s[i] == a) nt[i] = now;
        else if(s[i] == b) now = i;
    }
}
int main()
{
    while(scanf("%s",s)!=EOF){
        memset(nt,-1,sizeof nt);
        len = strlen(s); ans = N;
        slove('m','u'); slove('c','m'); slove('z','c');
        for(int i=0;i<len;i++){
            if(s[i]=='z'){
                int now = i;
                for(int j=0;j<3&&~now;j++){
                    now = nt[now];
                }
                if(now==-1) continue;
                ans = min(ans, now-i-3);
            }
        }
        printf("%d\n",ans==N?-1:ans);
    }
    return 0;
}






D CC的神奇背包

贪心,将所有物品分为放了之后包剩余容量变大和变小的两种,然后分别按体积从小到大排序,然后先放变大的,再放变小的,每次放置更新包的体积,若有一次不能再放入某一物品,则输出no

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define LL long long
const int N = 1e5 + 10;
int T,n,m,x,y,z;
struct node{
    int a,b;
}a[N],b[N];
bool cmp(node a,node b){
    return a.a<b.a;
}
int main()
{
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        int cnt1 = 0, cnt2 = 0;
        for(int i=0;i<n;i++){
            scanf("%d%d",&x,&y);
            if(x<=m&&y-x>=0){
                m += y-x;
            }else{
                if(y-x>=0) {
                    a[cnt1].a = x; a[cnt1++].b =y;
                }else {
                    b[cnt2].a = x; b[cnt2++].b =y;
                }
            }
        }
        int flag = 1;
        sort(a,a+cnt1,cmp); sort(b,b+cnt2,cmp);
        for(int i=0;i<cnt1;i++){
            if(m<a[i].a){
                flag = 0; break;
            }else{
                m -= a[i].a - a[i].b;
            }
        }
        if(flag){
            for(int i=0;i<cnt2;i++){
                if(m<b[i].a){
                    flag = 0; break;
                }else{
                    m -= b[i].a - b[i].b;
                }
            }
        }
        if(!flag){
            printf("no\n");
        }else{
            printf("yes\n");
        }
        
    }
    return 0;
}



E Pizza

贪心,分为n块质量为1的,答案就是k,签到题 ,数据超int

#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
#define LL long long
LL T,n,m;
int main()
{
    scanf("%lld",&T);
    while(T--){
        scanf("%lld%lld",&n,&m);
        printf("%lld\n",m);
    }
    return 0;
}




G 特产

签到题,两数相减就是答案

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define LL long long
int T;
LL n,m;
int main()
{
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld",&n,&m);
        printf("%lld\n",m-n);
    }
    return 0;
}



H 剪纸

题意就是有一个大小为n*n的正方形,将其一刀剪成两半,且两半要完全相同,求共能剪出多少种不同的形状(旋转后同样不同)

和今年浙江的蓝桥省赛有一题是一样的,因为要完全相同,所以一定是中心对称图形,以中心点为起点DFS求出所有的剪的线路,两边同时向外走,走的方向要想反,碰到边界就结束了,此时方案数加一,然后最终答案要旋转后也不能相同,所以最终答案为所有线路方案/4


#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
int T,n;
int dir[4][2] = {0,1,1,0,0,-1,-1,0};
int rdir[4][2] = {0,-1,-1,0,0,1,1,0};
int vis[15][15],ans;
bool check(int x,int y){
    if(x<0||x>n||y<0||y>n||vis[x][y]) return false;
    return true;
}
void dfs(int x1,int y1,int x2,int y2){
    if(x1==0||x1==n||y1==0||y1==n){
        ans++;
        return;
    }
    vis[x1][y1] = vis[x2][y2] = 1;
    for(int i=0;i<4;i++){
        int X1 = x1 + dir[i][0];
        int Y1 = y1 + dir[i][1];
        int X2 = x2 + rdir[i][0];
        int Y2 = y2 + rdir[i][1];
        if(!check(X1, Y1)||!check(X2, Y2)) continue;
        dfs(X1,Y1,X2,Y2);
    }
    vis[x1][y1] = vis[x2][y2] = 0;
}
int main()
{
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        if(n%2){
            printf("0\n");
            continue;
        }
        ans = 0;
        dfs(n/2,n/2,n/2,n/2);
        printf("%d\n",ans/4);
    }
    return 0;
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值