湖南大学ACM程序设计新生杯大赛(同步赛)(重现赛)

比赛地址传送口
A.Array
ps:待补
Array题解

B.Build
ps:待补
Build题解

C.Do you like banana? 计算几何
题意:判断线段是否相交
思路:向量叉乘
线段相交判定知识点参考
ac代码:

#include<iostream>
#include<cstdio>
#define ZERO 1e-9

using namespace std;

struct point{
    double x,y;
};

double vector_mul(point A,point B)//向量乘法
{
    return (A.x*B.y-B.x*A.y);
}

void negative(point &A,point &B)
{
    A.x=-B.x,A.y=-B.y;//取反
}

bool is_intersect(point A,point B,point C,point D)
{
	//计算叉乘((AC*AD)*(BC*BD))和叉乘((DA*DB)*(CA*CB)),若二者皆非正则相交,否则不相交
    point AC,AD,DA,DB,BC,BD,CA,CB;
    AC.x=C.x-A.x,AC.y=C.y-A.y;
    AD.x=D.x-A.x,AD.y=D.y-A.y;
    DB.x=B.x-D.x,DB.y=B.y-D.y;
    BC.x=C.x-B.x,BC.y=C.y-B.y;
    negative(DA,AD);
    negative(BD, DB);
    negative(CB, BC);
    negative(CA,AC);
    double res1=vector_mul(AC,AD);
    double res2=vector_mul(BC,BD);
    double res3=vector_mul(DA,DB);
    double res4=vector_mul(CA,CB);
    if(res1*res2<=ZERO&&res3*res4<=ZERO)return true;
    return false;
}

int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        point A,B,C,D;
        cin>>A.x>>A.y>>B.x>>B.y>>C.x>>C.y>>D.x>>D.y;
        if(is_intersect(A,B,C,D))cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
    return 0;
}

D.number 暴力打表+去重
分析:n的范围是5*1e7,因为要取2次方+3次方+4次方的和在n范围内,取个1e4就已经足够了,没必要取到1e7,况且取到1e7还容易爆,打好1e4范围内的一个质数表以后for循环暴力判断条件就行,要注意的一个点是要记得去重,因为有的不同次方组合的和是一样的,只能归成一种,用vis数组标记去重即可

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N=1e4;
int primes[N],cnt,p2[N],p3[N],p4[N];
bool vis[50000000+3];

void get_primes(int n)
{
    for(int i=2;i<=n;i++){
        if(!vis[i])primes[cnt++]=i;
        for(int j=0;primes[j]<=n/i;j++){
            vis[i*primes[j]]=true;
            if(i%primes[j]==0)break;
        }
    }
}

int main()
{
    int n;
    cin>>n;
    get_primes(1e4);
    int ans=0;
    memset(vis,false,sizeof(vis));
    for(int i=0;i<cnt;i++){
        if(primes[i]*primes[i]>n)break;
        for(int j=0;j<cnt;j++){
            if(primes[j]*primes[j]*primes[j]>n)break;
            for(int k=0;k<cnt;k++){
                int t=primes[i]*primes[i]+primes[j]*primes[j]*primes[j]+primes[k]*primes[k]*primes[k]*primes[k];
                if(t>n)break;
                if(vis[t])continue;
                vis[t]=true;ans++;
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}

ps:郁闷,没有去重一直不通过,而且老是怀疑这题暴力真能过吗,然后。。。一直没过。。因为没有计算好所需范围以及没有加上一些语句用来跳过一些不必要的判断加快程序运行,再加上没有考虑去重,都导致我这题没能ac,吸取教训

E.Permutation 规律
思路:

#include<iostream>

using namespace std;

int main()
{
    int n;
    cin>>n;
    if(n<=2)cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
    return 0;
}

G.The heap of socks
思路:map容器

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

using namespace std;

int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        map<int,int> mp;
        for(int i=0;i<n;i++){
            int x;
            cin>>x;
            mp[x]++;
        }
        int sum=0,i=0;
        for(auto it:mp){
            while(it.second--){
                sum+=it.first;
                i++;
                if(i==2)break;
            }
            if(i==2)break;
        }
        cout<<sum<<endl;
    }
    return 0;
}

H.Yuanyuan Long and His Ballons 公式题
分析:环染色问题公式直接代上去就行,题目中说要取模,因此计算次方时要用快速幂
公式:ans=(-1)^n*(k-1)+(k-1) ^n

#include<iostream>

using namespace std;

typedef long long ll;
const ll mod=100000007;

ll quick_pow(ll x,ll y,ll mod)
{
    ll ans=1;
    while(y){
        if(y&1)ans=(ans*x)%mod;
        x=(x*x)%mod;
        y>>=1;
    }
    return ans%mod;
}

int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        int n,k;
        cin>>n>>k;
        cout<<quick_pow(-1,n,mod)*(k-1)+quick_pow(k-1,n,mod)<<endl;
    }
    return 0;
}

ps:补题才晓得这居然直接用公式的,才知道有公式,高中数学没学好,现在还得补以前的坑 _
I.Piglet treasure hunt Series I
ps:待补
题解
J.Piglet treasure hunt Series II
ps:待补
题解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值