2014 Multi-University Training Contest 1

11.22 号 训练。。。

中学生已经开始虐场了吗
这里写图片描述

A
起手发现是个博弈,我就去看了,发现数据很大,会超时,果断打了个表。。。
然后一眼就发现规律了。
1–(p-2)都是0 ,只有 p-1的v>0 。 所以我们只要找有多少个这样的循环节,判断下奇偶就行。

while(~scanf("%d %d",&n,&p)){
        int len=p-1;
        int num=n/len;
        if(num&1){
            printf("YES\n");
        }
        else
            printf("NO\n");
    }

D
很巧妙地贪心

for(int i=1;i<=m;i++){  //遍历任务
             //cnt 放在外面初始化,里面要接着上面的遍历
            while(cnt<=n && ma[cnt].t>=task[i].t){  //标记所有的(时间上能完成这个任务的机器的难度)
                vis[ ma[cnt].v ]++;
                cnt++;
            }

            for(int j=task[i].v;j<=100;j++){  //遍历所有难度
                if(vis[j]){
                    num++;
                    vis[j]--;
                    ans+=500*task[i].t + task[i].v*2;
                    break;
                }
            }
        }

1009
http://acm.hdu.edu.cn/showproblem.php?pid=4869
题意:
m位 0 ,n次操作,每次操作可以反转x张牌,问最后可能形成多少种结果;
最后有3个1 和 4和1 形成的数字肯定是不同的
一开始想的是: for 0-m 观察是否有可能最后只翻转 i 张牌。然后lucas定理累加
然而 我们无法在log n 的时间复杂度中判断
然后我想预处理,把所有能形成的 翻转数量都写出来。。。
想了想 会TLE,因为m=1e5,形成的 种数最多也有1e5

我们经过手动推导,发现一个规律: 翻转数量 保持奇偶性,非奇即偶。
于是我们利用这个性质,找到 最后结果 最少的1 的数量(翻转数) 和 最多的1的数量。 可以证明 [l,r] 肯定是连续的, 即 最少 +2 +2 +2 = 最多的

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<string.h>
#include<map>
using namespace std;

#define ll __int64
#define mod 1000000009
const int maxn=2000001;  //这个应该就最大了吧,意味着这n,m 最多这么大

ll fac[maxn];
void init(ll p)
{
    fac[0] = 1;
    for(int i = 1;i < p;i++)
        fac[i] = fac[i-1]*i%mod;     //这里不是%p !!!
}
ll qpow(ll a,ll b)
{
    ll ans=1;a%=mod;
    for(ll i=b;i;i>>=1,a=a*a%mod)
        if(i&1)ans=ans*a%mod;
    return ans;
}
ll C(ll n,ll m)
{
    if(m>n||m<0) return 0;
    ll s1=fac[n],s2=fac[n-m]*fac[m]%mod;
    return s1*qpow(s2,mod-2)%mod;
}

int main() {
    freopen("1.txt","r",stdin);
    init(maxn);
    ll n,m;
    while (~scanf("%I64d %I64d", &n, &m)) {
        int l,r,lmin,rmax; //当前最小的1 ,当前最大的1  的个数
        l=r=0; //最终的[l,r]
        for (int i = 1; i <= n; i++) {
            int x;
            scanf("%d", &x);
            if(l>=x) lmin=l-x;  //把x个1翻回来
            else if(r>=x){
                if( (l%2)==(x%2) ) //判断x和l的奇偶性
                    lmin=0;
                else
                    lmin=1;
            }
            else //x>r
                lmin= x-r;

            if(r+x<=m)
                rmax=r+x;
            else if(l+x<=m){
                if( ( (l+x)%2)==(m%2) ) //判断x和r的奇偶性
                    rmax=m;
                else
                    rmax=m-1;
            }
            else{   //l+x>m别忘记这种情况
                rmax= m-(x-(m-l));
            }
            l=lmin,r=rmax;
        }
        ll ans = 0;
//      printf("l,r=%d %d",l,r);
        for(int i=l;i<=r;i+=2){
            ans+=C(m,i);
            ans%=mod;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值