ccpc网络赛重赛题解

1.Primality Test
题意:f(x)代表大于x的第一个质数,求g(x)=[(f(x)+f(f(x)))/2],就是求大于x的下一个质数和下下一个质数加起来除2,问g(x)是否为质数
思路:枚举了几个x,发现除了当x=1,g(x)为质数,否则当x>1时,g(x)为偶数,不可能为质数
核心代码

if(x==1)
{
	cout<<"YES"<<endl;
}
else 
{
	cout<<"NO"<<endl;
}

2.Kanade Doesn’t Want to Learn CG
题意:给你一个抛物线投篮,问能不能进,撞到篮板水平速度变向,竖直速度不变
思路:两种情况进球(1)直接进球(2)打到篮板反弹进球
核心代码

#include<iostream>
#include<algorithm>
using namespace std;
double a, b, c, x0, x1, z0, z1, z2;
double fun(double x)
{
	return a * x * x + b * x + c;
}
int main()
{
	int t;
	cin >> t;
	while (t--) {
		cin >> a >> b >> c;
		cin >> x0 >> x1 >> z0 >> z1 >> z2;
		double yy0 = fun(x0);
		double yy1 = fun(x1);
		double dyy0 = fun(x0 + 2 * (x1 - x0));
		if (yy0 > z0 && yy1 <= z2 && yy1 > z0)
		{
			if (dyy0 < z0)
			{
				cout << "Yes" << endl;
			}
			else
			{
				cout << "No" << endl;
			}
		}
		else if (yy0 > z0 && yy1 < z0)
		{
			cout << "Yes" << endl;
		}
		else
		{
			cout << "No" << endl;
		}
	}
}

3.Nun Heh Heh Aaaaaaaaaaa
思路:统计号前缀数量,一旦统计好nunhehheh,和后面统计好的a的数量进行排列组合,要用快速幂,快速乘
核心代码

        for(int i=0; i<len; i++)
        {
            if(s[i]=='n')
            {
                num[3]+=num[2]%mod;
                num[1]++;

            }
            else if(s[i]=='u')
            {
                num[2]+=num[1]%mod;
            }
            else if(s[i]=='h')
            {
                num[7]+=num[6]%mod;
                num[6]+=num[5]%mod;
                num[4]+=num[3]%mod;
                num[9]=(num[9]+ksmc(num[8],(ksm(2,a[i+1])-1))%mod)%mod;            }
            else if (s[i]=='e')
            {
                num[8]+=num[7]%mod;
                num[5]+=num[4]%mod;
            }
        }

4.Monopoly
题意:玩大富翁,给你一个地图,首尾相连,只能一步一步走,每个地方都有权值x,如果该地方权值为正,则分数增加x,否则分数减少x,问如果要达到y分最少要走几步,如果达不到这个分数输出-1,能达到输出最少要走的步数
思路:设S为每一步的得分序列,要找到最小的i使S[i]=y;设地图走一圈的收益为sum
(1)sum>0
s[i]=s[j]+k*sum,(1<=j<=n,k>=0),如果s[j]越大,k越小,步数越少,且s[i]和s[j]模sum同余,所以我们要在与y模sum同余的数中找到小于等于y的最大整数,
(2)sum<0
把序列翻转过来,将需求反过来,同(1)处理
(3)sum==0
sum等于0就只要在(1~n)的s序列中找就行了,因为多走个循环没有收益
代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
const int maxn = 2e5+5;
ll a[maxn],p[maxn];
ll n,m,s;
map <ll,ll> vis;//用于当原数组前缀和为0
map <ll,vector<pll>> mp;//第一个数代表取模后的余数,pll的第一个代表可以减循环的数,第二个是位置
void solve()
{
    bool flag=0;
    cin>>n>>m;
        s=0;
        for(int i=1; i<=n; i++)
        {
            cin>>a[i];
            p[i]=p[i-1]+a[i];
            s+=a[i];
        }
    if(s<0)
    {
        flag=1;
        s=-s;
        for(int i=1;i<=n;i++)
        {
            p[i]=-p[i];
        }
    }
    if(s==0)
    {
        vis.clear();
        for(int i=1; i<=n; i++)
        {
            if(vis.find(p[i])==vis.end())//如果在vis没存过才存,因为答案要取最前面的
            {
                vis[p[i]]=i;
            }
        }
        while(m--)
        {
            ll x;
            cin>>x;
            if(x==0)
            {
                cout<<0<<endl;
                continue;
            }
            if(vis.find(x)==vis.end())
            {
                cout<<-1<<endl;
            }
            else
            {
                cout<<vis[x]<<endl;
            }
        }
        return ;
    }
    mp.clear();
    for(int i=1;i<=n;i++)
    {
        ll ys=(p[i]%s+s)%s;//保持余数为正数,要做索引
        mp[ys].push_back({-p[i],i});
    }
    for(auto it=mp.begin();it!=mp.end();it++)
    {
        sort(it->second.begin(),it->second.end());//it代表的是一个pair,it->first是key,it->second是value
    }
    while(m--)
    {
        ll x;
        cin>>x;
        if(x==0)
        {
            cout<<0<<endl;
            continue;
        }
        if(flag)x=-x;
        ll xys=(x%s+s)%s;
        if(mp.find(xys)==mp.end())
        {
            cout<<-1<<endl;//没找到
            continue;
        }
        pll as={-x,0};
        ll sum=lower_bound(begin(mp[xys]),end(mp[xys]),as)-mp[xys].begin();
        if(sum==mp[xys].size())
        {
            cout<<-1<<endl;
        }
        else
        {
            ll ans=mp[xys][sum].second;//相当于找到的s[j]
            ans+=(x+mp[xys][sum].first)/s*n;///抵消多余的圈数
            cout<<ans<<endl;
        }

    }
}
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        solve();
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值