cf刷题日记 2019 .1.21~~2019.1.25

Codeforces Round #533 (Div. 2) C. Ayoub and Lost Array &DP

http://codeforces.com/contest/1105/problem/C
题意:
给n,l,r。

一个n长的数组每个位置可以填区间l-r的值。

有多少种填法,使得数组每个位置相加的和是3的倍数

dp,

从1个数组扩展到n个数组,

dp[i][j]是加上第i个数组后,分别余0,1,2的个数。

#include <bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
long long  dp[200005][3];
int main()
{
    int n,l,r;
    while(cin>>n>>l>>r)
    {
        memset(dp,0,sizeof(dp));
        dp[0][0]=1,dp[0][1]=0,dp[0][2]=0;
        int x,y,z;

        x=r/3-(l-1)/3,y=(r+2)/3-(l+1)/3,z=(r+1)/3-l/3;
        //余0则是,i-1余0*自己余0+(i-1余1*自己余2)+(i-1余2*自己余1
        for(int i=1;i<=n;i++)
        {
            dp[i][0]=dp[i-1][0]*x%mod+dp[i-1][1]*z%mod+dp[i-1][2]*y%mod;
            dp[i][0]%=mod;
            dp[i][1]=dp[i-1][0]*y%mod+dp[i-1][1]*x%mod+dp[i-1][2]*z%mod;
            dp[i][1]%=mod;
            dp[i][2]=dp[i-1][0]*z%mod+dp[i-1][1]*y%mod+dp[i-1][2]*x%mod;
            dp[i][2]%=mod;

        }
        cout<<dp[n][0]<<endl;
    }
}

Codeforces Round #533 (Div. 2) D. Kilani and the Game

http://codeforces.com/contest/1105/problem/D

题意:
给n*m的地图,最多9个人,同时有每个人的扩张次数(我开始以为是直线扩张最大长度。。实际是能连续扩张次数。)

地图上有‘#’,‘.’,和数字,数字对应每个人的据点,

从1-n轮流扩张。

地图被扩张完后,输入每个人的据点数目。

垃圾题目 浪费时间 毁我青春。。
注意一点,当矩阵的空间不再减少时候直接结束

#include <bits/stdc++.h>
using namespace std;
int a[15];
int grp[1005][1005];
struct node
{
    node (int xx,int yy)
    {
        x=xx;
        y=yy;
    }
    int x,y;
};
int n,m,p;
vector<node> node_bfs[15];

vector<node >tem[2];

int s_sum;
int dfs(int depth,int max_depth,int bl,int num)
{
   // cout<<"num  "<<num<<' '<<depth<<endl;
    if(depth==max_depth) return bl;
    tem[!bl].clear();
    int z=0;
    for(int i=0;i<tem[bl].size();i++)
    {
        for(int x=-1;x<=1;x++)
        {
            for(int y=-1;y<=1;y++)
            {
                if(abs(x)!=abs(y))
                {

                    int xv=tem[bl][i].x+x;
                    int yv=tem[bl][i].y+y;
                   // cout<<"xx   yy   "<<num<<' '<<xv<<' '<<yv<<' '<<grp[xv][yv]<<endl;
                   // cout<<x<<' '<<y<<endl;
                    if(xv>0&&xv<=n&&yv>0&&yv<=m&&!grp[xv][yv])
                    {
                        z=1;
                        s_sum--;
                        grp[xv][yv]=num;
                        tem[!bl].push_back(node(xv,yv));
                    }
                }

            }
        }
    }
    if(z)
    {
        return dfs(depth+1,max_depth,!bl,num);
    }
    else
    {
        tem[!bl].clear();
        return !bl;
    }
}

int main()
{

    while(cin>>n>>m>>p)
    {
        s_sum=0;
        for(int i=1;i<=p;i++)
        {
            node_bfs[i].clear();
            cin>>a[i];
        }
        string s;char c;
        for(int i=1;i<=n;i++)
        {
            cin>>s;
            for(int j=1;j<=m;j++)
            {
                c=s[j-1];
                //cin>>c;
                if(c=='.')
                {
                    grp[i][j]=0;
                    s_sum++;
                }
                else if(c!='#')
                {
                    int v=c-'0';
                    grp[i][j]=v;
                    node_bfs[v].push_back(node(i,j));
                }
                else
                {
                    grp[i][j]=-1;
                }
            }
        }

        while(s_sum)
        {
            int qs=s_sum;
           // cout<<s_sum<<endl;
            for(int i=1;i<=p;i++)
            {
                tem[0]=node_bfs[i];
                int res=dfs(0,a[i],0,i);
                node_bfs[i]=tem[res];
                //swap(&node_bfs[i],&tem[res]);
            }//cout<<endl;
            if(qs==s_sum) break;




        }
        memset(a,0,sizeof(a));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                a[grp[i][j]]++;
                //cout<<grp[i][j]<<' ';
            }
        //    cout<<endl;
        }
        for(int i=1;i<=p;i++)
        {
            cout<<a[i]<<' ';
        }
        cout<<endl;


    }
}

标题 532 div2 F. Ivan and Burgers 线性基

http://codeforces.com/contest/1100/problem/F

题目大意:有n个汉堡店,每个店里最贵的汉堡是ci元,q次询问,从l到r,所能花费的最多钱数(结束与开始时的金额差),但是花钱不是直接的加减,规则是手里有d元,要花费c元,那支付只后,他还有d^c元。开始是他有非常多个1(rich)。

具体思路:贪心,我们按照右边界的大小进行排序,小的在上面,大的往下安排,然后每一次我们寻找1–> r区间内的线性基,如果当前的线性基能往后移动,我们就选取后面的这个线性基(因为我们对输入的数据进行了排序,后面的r肯定是大的,所以我们将选取的线性基尽量的往后安排肯定是没有问题的,然后我们查询的时候,看一下当前位上有线性基的时候,先判断这个线性基取的时候是从哪个数里面取出来的,然后再看一下这个数是不是大于l的,如果是的话,这个线性基就是可用的,我们通过这些线性基寻找一个最大值就可以了)

最后解题思路就是离线的线性基。
然后 查询l 到r 区间中的最大值是谁 从高位到低位便利

#include <bits/stdc++.h>
using namespace std;
const int maxn=500005;
int nums[maxn];
struct node
{
    int l,r;
    int vis;
}tag[maxn];

bool cmp1(node a,node b)
{
    if(a.r==b.r) return a.l<b.l;
    return a.r<b.r;
}

int a[25],pos[25];
bool liner(int val,int p)
{
    for (int i=20;i>=0;i--)
    {
        if (val&(1LL<<i))
        {
            if (!a[i])
            {
                a[i]=val;
                pos[i]=p;
                break;
            }
            if(pos[i]<p)
            {
                swap(pos[i],p);
                swap(a[i],val);
            }
            val^=a[i];
        }
    }
    //cout<<"liner   "<<val<<endl;
    return val>0;
}

int query_maxs(int l)
{
    int ret=0;
    for (int i=20;i>=0;i--)
        if ((ret^a[i])>ret&&pos[i]>=l)
            ret^=a[i];
    return ret;
}
int ans[maxn];

int ces[maxn];
int main()
{
    int n;
    while(cin>>n)
    {
        for(int i=1;i<=n;i++)
        {
           // cin>>ces[i];
           scanf("%d",&ces[i]);
        }

        int q;
       // cin>>q;
        scanf("%d",&q);
        for(int i=0;i<q;i++)
        {
            //cin>>tag[i].l>>tag[i].r;
            scanf("%d%d",&tag[i].l,&tag[i].r);
            tag[i].vis=i;
        }

        sort(tag,tag+q,cmp1);
        int r=1;
        for(int i=0;i<q;i++)
        {
            while(r<=tag[i].r)
            {
                liner(ces[r],r);
                r++;
            }
           // cout<<"ads a    "<<query_maxs(tag[i].l)<<' '<<tag[i].l<<' '<<tag[i].r<<' '<<r<<endl;
            ans[tag[i].vis]=query_maxs(tag[i].l);
        }

        for(int i=0;i<q;i++)
        {
            cout<<ans[i]<<endl;
        }




    }
}

标题 Educational Codeforces Round 58 (Rated for Div. 2)F. Trucks and Cities

http://codeforces.com/contest/1101/problem/F

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 405;
int dp[maxn][maxn]; // dp[i][j][k] 表示从i出发到达j中间停留k次的最长间隔。
int a[maxn];
int pos[maxn];
struct data
{
    int f,c,r;
    data(){}
    data(int ff,int cc,int rr)
    {
        f=ff;
        c=cc;
        r=rr;
    }
};
vector<data> G[maxn];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=m;i++)
    {
        int s,f,c,r;
        scanf("%d%d%d%d",&s,&f,&c,&r);
        G[s].push_back(data(f,c,r));//离线处理每个起点为s的查询
    }
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            dp[j][0]=a[j]-a[i];
            int pos=0;
            for(int k=1;k<=n;k++)
            {
                dp[j][k]=a[j]-a[i];
                while(pos+1<=j&&dp[pos+1][k-1]<a[j]-a[pos+1]) pos++;//单调队列优化DP
                dp[j][k]=min(dp[j][k],min(a[j]-a[pos],dp[pos+1][k-1]));
            }
        }
        for(int j=0;j<G[i].size();j++)
        {
            int f=G[i][j].f;
            int c=G[i][j].c;
            int r=G[i][j].r;
            ans=max(ans,1LL*dp[f][r]*c);
        }
    }
    printf("%lld\n",ans);
    return 0;
}

G. (Zero XOR Subset)-less

Educational Codeforces Round 58 (Rated for Div. 2)

http://codeforces.com/contest/1101/problem/G

解题思路 线性基的性质

#include <bits/stdc++.h>
using namespace std;
int a[200005],p[66];
void Linear(int x)
{
    int xe=x;
   // cout<<x<<endl;
    for(int i=31;i>=0;i--)
    {
        if((x&(1<<i))==0) continue ;
        if(p[i]==0)
        {

            p[i]=x;
            break;
        }
        else x^=p[i];  
        //cout<<"asd  "<<i<<' '<<x<<' '<<xe<<endl;

    }
}
int main()
{
    int n;
    while(cin>>n)
    {
        memset(p,0,sizeof(p));
        int t=0;
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
            if(i==0) t=a[i];
            else t^=a[i];
        }
        if(t==0 )
        {
            cout<<-1<<endl;
            continue;
        }
        else
        {
            for(int i=0;i<n;i++)
            {
                Linear(a[i]);
            }
            int ans=0;
            for(int i=31;i>=0;i--)
            {

                if(p[i])
                {
                    ans++;
                   // cout<<i<<' '<<p[i]<<endl;
                }
            }
            cout<<ans<<endl;
        }
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值