被虐中成长——2014年多校训练赛第一场解题报告

来源:互联网 发布:xsplit直播软件下载 编辑:程序博客网 时间:2024/05/21 22:19

妥妥的被虐,第一题其实就是猜出来的,第二题错好了好多发,最后乱改压时间过了,实际上是自己粗心写错了地方。。。。

A题,看了赛后解题报告才知道是什么费马小定理,我们是自己列出数据算发现的规律,只有第i个(i%(p-1)==0)的球有分数,所以计算有几个有分数的球就可以了。

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <cmath>using namespace std;int main(){int n,p;while(~scanf("%d%d",&n,&p)){int ans;ans=n/(p-1);if(ans%2==1){cout<<"YES"<<endl;}else{cout<<"NO"<<endl;}}return 0;}

D题Task

有n台机器最大工作时间是t,最高难度是l,m个任务,工作时间是t,难度是l,每个任务只能由一台机器完成,每个机器只能完成一个任务,每个任务的赏金是500*t+2*l,求最多能得到多少赏金,输出完成的任务的个数以及赏金。

数据量很大,很容易T,做法应该是让每一个机器完成时间最相近的任务,刚开始没找到思路乱搞一直T or WA。

最后做法是:根据l的级别做,开1440个栈对应需要多少时间的任务,l的等级从1到100,每次把对应等级的任务压进所需要时间的栈,然后搜索该等级的机器最大能完成的任务,直接搜时间即可,然后把这个出栈,继续下一个机器,直到等级大于i。

#include<cstring>#include<string>#include<fstream>#include<iostream>#include<iomanip>#include<cstdio>#include<cctype>#include<algorithm>#include<queue>#include<map>#include<set>#include<vector>#include<stack>#include<ctime>#include<cstdlib>#include<functional>#include<cmath>using namespace std;#define PI acos(-1.0)#define MAXN 100010#define eps 1e-7#define INF 0x7FFFFFFF#define ff sqrt(5.0)typedef long long ll;struct node{    int t;    int l;}task[110000],mach[110000];int n,m;stack<int>s[1500];bool cmp(node a,node b){    if(a.l==b.l) return a.t<b.t;    return a.l<b.l;}int main(){    int n,m;    while(~scanf("%d%d",&n,&m))    {        for(int i=0;i<n;i++)        {            scanf("%d%d",&mach[i].t,&mach[i].l);        }        for(int i=0;i<m;i++)        {            scanf("%d%d",&task[i].t,&task[i].l);        }        sort(mach,mach+n,cmp);        sort(task,task+m,cmp);for(int i=0;i<1500;i++)        {           while(!s[i].empty())           {           s[i].pop();           }        }        int p,q;        int cnt=0;        long long ans=0LL;        p=0;        q=0;        for(int i=0;i<=100;i++)        {            while(task[p].l<=i&&p<m)            {                //cout<<task[p].l<<endl;                s[task[p].t].push(task[p].l);                p++;            }            while(mach[q].l<=i&&q<n)            {                for(int j=mach[q].t;j>=0;j--)                {                    if(!s[j].empty())                    {                        int tmp=s[j].top();                        s[j].pop();                        cnt++;                        ans+=tmp*2+500*j;                        break;                    }                }                q++;            }        }        cout<<cnt<<" "<<ans<<endl;    }}

I题 Turn the poker(组合数)(赛后)
翻纸牌游戏,给出操作次数n和纸牌数目m,每次操作选择x张智牌翻转,问最后牌的结果有多少种情况。

把最开始的牌都认为处于0状态,翻转后变为1,最后的答案就是ans=∑C(m,k),C(m,k)为组合数,k为所有能取到的1的可能个数。详细的解释,先了解最后1的个数的奇偶性,跟所有翻牌数的和的奇偶相同(每次翻牌,要么0->1,要么1->0,都是在改变1的个数奇偶)。之后我们需要找到最少有i个1,以及最大有j个1;i的情况就是有1就翻1,j的情况就是有0就翻0,而中间的情况时,取偶数步数,一半翻0,一半翻1,保持不变,所以可以确定i,i+2,i+4,...,j-2,j都能被翻到。最后ans=∑C(m,k)(i<=k<=j&&k%2==i%2)。

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <queue>#include <algorithm>#include <ctime>#define ll __int64using namespace std;const int maxn=1e5+10;const int mod=1e9+9;ll c[maxn];ll pow_mod(ll a ,ll b){    ll s=1;    while(b)    {        if(b&1)        {            s=s*a%mod;        }        a=a*a%mod;        b=b>>1;    }    return s;}int main(){    int n,m;    int x;    int p,q;    int high,low;//上下限     while(scanf("%d%d",&n,&m)!=EOF)    {        high=0;        low=0;        for(int i=0;i<n;i++)        {            scanf("%d",&x);            if(low>=x)            {                p=low-x;            }            else if(high>=x)            {                p=((low&1)==(x&1)?0:1);             }            else            {                p=x-high;            }            if(high+x<=m)            {                q=high+x;            }            else if(low+x<=m)            {                q=(((low+x)&1)==(m&1)?m:m-1);            }            else            {                q=2*m-(low+x);            }            low=p;            high=q;        }        ll ans=0;        c[0]=1;        if(low==0)        {            ans+=c[0];        }        for(int i=1;i<=high;i++)        {            if(m-i<i)            {                c[i]=c[m-i];            }            else            {                c[i]=c[i-1]*(m-i+1)%mod*pow_mod(i,mod-2)%mod;            }            if(i>=low&&(i&1)==(low&1))            {                ans+=c[i];            }        }          printf("%I64d\n",ans%mod);     }}


0 0
原创粉丝点击