首页 > 代码库 > 2014多校联合第一场

2014多校联合第一场

1001:Couple doubi

暴力打表找规律可知,对于任意的p。

(1^i+2^i+...+(p-1)^i)%p={    

非0     ,i%(p-1)==0

 0        ,  i%(p-1)!=0

所以,结果就很显然了。

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
using namespace std;
#define eps 1e-4
#define zero(x) ((fabs(x)<eps)?0:x)
int main()
{
    int n,k;
    while(~scanf("%d%d",&n,&k))
    {
        int x=n/(k-1);
        if(x%2==0)cout<<"NO"<<endl;
        else cout<<"YES"<<endl;
    }
    return 0;
}

1004:Task

很显然,y对总值的影响远小于x。

所以:

按y排序,y小的放在前面,然后按x排序,x小的放在前面,然后按属性排序,任务放在前面。

然后依次遍历这些点。

如果当前点为任务:

把当前任务的价值放入set中。

如果当前点为机器:

在set中寻找最后一个比当前机器的价值小的任务。

#include <iostream>
#include<stdio.h>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
#define LL long long
struct list
{
    int x;
    int y;
    int s;
    int leap;
    friend bool operator <(const list &a,const list &b)
    {
        if(a.y!=b.y)return a.y<b.y;
        else if(a.x!=b.x)return a.x<b.x;
        else return a.leap<b.leap;
    }
}node[220000];
multiset<int>st;
multiset<int>::iterator it;
int sea(int x)
{
    if(st.size()==0)return 0;
    it=st.begin();
    if(x<(*it))return 0;
    it=st.lower_bound(x);
    if(it==st.end())
    {
        it=st.end();
        it--;
        int ans=(*it);
        st.erase(it);
        return ans;
    }
    if((*it)==x)
    {
        st.erase(it);
        return x;
    }
    it--;
    int ans=(*it);
    st.erase(it);
    return ans;
}
void dos(int n)
{
    int x=0;
    LL sum=0;
    st.clear();
    for(int i=1;i<=n;i++)
    {
        if(node[i].leap==1)
        {
            int res=sea(node[i].s);
            if(res)
            {
                x++;
                sum+=(LL)res;
            }
        }
        else
        {
            st.insert(node[i].s);
        }
    }
    cout<<x<<" "<<sum<<endl;
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&node[i].x,&node[i].y);
            node[i].leap=1;
            node[i].s=node[i].x*500+node[i].y*2;
        }
        for(int i=n+1;i<=n+m;i++)
        {
            scanf("%d%d",&node[i].x,&node[i].y);
            node[i].leap=0;
            node[i].s=node[i].x*500+node[i].y*2;
        }
        sort(node+1,node+n+m+1);
        for(int i=1;i<=n+m;i++)
        {
            //cout<<node[i].x<<" "<<node[i].y<<" "<<node[i].leap<<endl;
        }
        dos(n+m);
    }
    return 0;
}

1005:Peter‘s Hobby

wh[i][j]:天气为i,叶子的状态为j的概率。

ww[i][j]:今天天气为i,明天天气为j的概率。

st[i]:第一天天气为i的概率。

叶子的状态序列为{b1,b2...bn}

那么对于某个天气序列{a1,a2....an}的概率为:

st[a1]*wh[a1][b1]* ww[a1][a2] *wh[a2][b2]* ww[a2][a3]* wh[a3][b3]*........*ww[an-1][an]*wh[an][bn];

因为结果有可能很小,所以用log把乘法转化为加法。

然后就是很明显的dp求路径了。。。。

#include <iostream>
#include<stdio.h>
#include<set>
#include<vector>
#include<math.h>
#include<algorithm>
#include<string.h>
using namespace std;
#define LL long long
#define INF 99999999
#define eps 1e-6
#define zero(x) ((fabs(x)<eps)?0:x)
double wh[3][4]={
    {0.6,0.2,0.15,0.05},
    {0.25,0.3,0.2,0.25},
    {0.05,0.10,0.35,0.5}
};
double ww[3][3]={
    {0.5,0.375,0.125},
    {0.25,0.125,0.625},
    {0.25,0.375,0.375}
};
double st[3]={0.63,0.17,0.2};
double dp[55][3];
double ans[55][3];
vector<int>vec;
int a[110];
char str[110];
void dfs(int x,int y)
{
    //cout<<y<<endl;
    vec.push_back(y);
    if(x==1)
    {
        return ;
    }
    for(int i=2;i>=0;i--)
    {
        if(zero(ans[x][y]-(ans[x-1][i]+dp[x][y]+ww[i][y]))==0)
        {
            dfs(x-1,i);
            break;
        }
    }
}
int main()
{
    int T,cas,n;
    scanf("%d",&T);
    cas=0;
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            ww[i][j]=log(ww[i][j]);
        }
    }
    while(T--)
    {
        vec.clear();
        cas++;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",str);
            int x=strlen(str);
            if(x==3)a[i]=0;
            else if(x==6)a[i]=1;
            else if(x==4)a[i]=2;
            else if(x==5)a[i]=3;
        }
        memset(dp,0,sizeof(dp));
        double s=0;
        for(int i=1;i<=n;i++)
        {
            s=0;
            for(int j=0;j<3;j++)
            {
                dp[i][j]=wh[j][a[i]];
                s+=dp[i][j];
            }
            for(int j=0;j<3;j++)dp[i][j]=dp[i][j]/s;
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<3;j++)
            {
                dp[i][j]=log(dp[i][j]);
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<3;j++)ans[i][j]=-INF;
        }
        for(int j=0;j<3;j++)
        {
            ans[1][j]=dp[1][j]+log(st[j]);
        }
        for(int i=2;i<=n;i++)
        {
            for(int j=0;j<3;j++)
            {
                for(int k=0;k<3;k++)
                {
                    double ps=ans[i-1][k]+ww[k][j]+dp[i][j];
                    ans[i][j]=max(ans[i][j],ps);
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<3;j++)
            {
               // cout<<ans[i][j]<<" ";
            }
         //   cout<<endl;
        }
        double maxx=-INF;
        int p=0;
        for(int j=0;j<3;j++)
        {
            if(maxx<ans[n][j])
            {
                maxx=ans[n][j];
                p=j;
             //   cout<<maxx<<" "<<p<<endl;
            }
        }
        dfs(n,p);
        printf("Case #%d:\n",cas);
        for(int i=n-1;i>=0;i--)
        {
            if(vec[i]==0)puts("Sunny");
            if(vec[i]==1)puts("Cloudy");
            if(vec[i]==2)puts("Rainy");
        }
    }
    return 0;
}
1009:Turn the pokers

假如初始全部是正面(状态为0)。

全部操作完成后,正面的个数为x个。

那么x有很多种情况。假如分别为{x1,x2....xk}

那么结果为C(m,x1)+C(m,x2)+C(m,x3)+...+C(m,xk).

很明显可以得知x1,x2...xk奇偶性一致。

我们试验几组例子可知,x1,x2...xk是一段连续的区间。

那么我们只需要求出x1,xk就可以了。

然后我们就可以每走一步,根据上一步的x1,xk,确定这一步之后的x1,xk.

#include <iostream>
#include<cmath>
#include<algorithm>
#include<cstdio>
using namespace std;
#define LL long long
#define mod 1000000009
LL jie[110000];
void init()
{
    jie[0]=1;
    jie[1]=1;
    for(int i=2;i<=100000;i++)
    {
        jie[i]=jie[i-1]*i;
        jie[i]=jie[i]%mod;
    }
}
LL qmod(LL x,LL y)
{
    if(y==0)return 1;
    if(y==1)return x%mod;
    LL ans=qmod(x,y/2);
    ans=(ans*ans)%mod;
    if(y%2)ans=(ans*x)%mod;
    return ans;
}
LL dos(int n,int m)
{
    LL ans=jie[n];
    ans=(ans*qmod((jie[m]*jie[n-m])%mod,mod-2))%mod;
    return ans;
}
int main()
{
    init();
    int n,m,x;
    while(~scanf("%d%d",&n,&m))
    {
        int l,r;
        scanf("%d",&x);
        l=r=x;
        int ll,rr;
        for(int i=2;i<=n;i++)
        {
            scanf("%d",&x);
            ll=l-x;
            rr=r+x;
            if(ll<0)
            {
                if(r-x<0)ll=0+x-r;
                else ll=((l-x)%2+2)%2;
            }
            if(rr>m)
            {
                if(l+x<=m)rr=m-(r+x)%2;
                else rr=m-(l+x-m);
            }
            l=ll;
            r=rr;
        }
        LL ans=0;
        for(int i=l;i<=r;i+=2)
        {
            ans+=dos(m,i);
            ans=ans%mod;
        }
        cout<<ans<<endl;
    }
    return 0;
}