ACM-ICPC 2018 徐州赛区网络预赛 A B F G H I 持续更新

 

/**
 A:Hard to prepare
题意:给你一个n,一个k,表示n个人环形坐开后,每人从[0,2^k)中选一个数;
要求使得任意相邻两个人所选得数字得同或值不为0
思路:首先我们发现两个数同或为0,那么这两个数抑或为2^k-1;然而假设一个数字为a
要使a(xor)x=2^k-1;那么x=2^k-1(xor)a即可,发现这是一个确定好得数,那么我们是不是会去想到一个问题
给你一个环让你去填色,相邻得块不能同色
哇 是不是觉得超级像,嗯是的简直一样;
按照高中学的公式按照这个https://blog.csdn.net/henuwhr/article/details/54934122
去递推一下就找到公式了
*/
#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int mod=1e9+7;

ll quick(ll x,ll y){
    ll ans=1;
    while(y){
        if(y&1)ans=ans*x%mod;
        x=x*x%mod;
        y=y>>1;
    }
    return ans;
}

int main()
{
    int T;
    ll tmp,ans,x,k;
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld",&x,&k);
        tmp=quick(2,k)%mod;
        if(x&1){
            ans=((quick(tmp-1,x))%mod+1)%mod;
        }
        else{
            ans=((tmp-1)%mod+quick(tmp-1,x)%mod)%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

/**
B : BE, GE or NE
题意:两个人在玩一个人想使得结果最大,一个人想使得结果最小 a+ b- c*-1
思路:因为要满足GE,分数越高越好,而要满足BE,
分数越低越好,因此A的策略应当是取尽可能大的,
B的策略应当是取尽可能小的。此时我们不妨用dp去解决。
我们设dp[i][j]表示在第i个关卡中,分数为j分时所能获得的最大的分数。
而对于i为奇数情况下是A选,则i的状态要优先选最大值;
而对于i为偶数的情况下B选,则优先选最小。
而需要注意的是,因为j的值可能为负数,因此我们可以用map(常数较大)
或者直接将j+100去递推dp。
*/
#include<bits/stdc++.h>
#define maxn 1005
using namespace std;
int dp[maxn][205];
int a[maxn],b[maxn],c[maxn];
const int x=100;
int main()
{
    int n,m,k,l;
    int now1,now2,now3;
    scanf("%d%d%d%d",&n,&m,&k,&l);
    for(int i=1;i<=n;i++)
        scanf("%d%d%d",&a[i],&b[i],&c[i]);
    for(int i=-100;i<=100;i++)
        dp[n+1][i+x]=i;
    for(int i=n;i>=1;i--){
            for(int j=-100;j<=100;j++){
                now1=dp[i+1][min(j+a[i],100)+x];
                now2=dp[i+1][max(j-b[i],-100)+x];
                now3=dp[i+1][-j+x];
            if(i&1){
                dp[i][j+x]=-100;
                if(a[i]) dp[i][j+x]=max(dp[i][j+x],now1);
                if(b[i]) dp[i][j+x]=max(dp[i][j+x],now2);
                if(c[i]) dp[i][j+x]=max(dp[i][j+x],now3);
            }
            else{
                dp[i][j+x]=100;
                if(a[i]) dp[i][j+x]=min(dp[i][j+x],now1);
                if(b[i]) dp[i][j+x]=min(dp[i][j+x],now2);
                if(c[i]) dp[i][j+x]=min(dp[i][j+x],now3);
            }
        }
    }
    if(dp[1][m+x]>=k) puts("Good Ending");
    else if(dp[1][m+x]<=l) puts("Bad Ending");
    else puts("Normal Ending");
    return 0;
}
/**
H. Ryuji doesn't want to study
链接:https://nanti.jisuanke.com/t/31460
题意:单点修改+区间求和
[l,r] ...a[l]*L+a[l+1]*(L-1)+a[l+2]*(L-2)+....a[r]....
L为区间长度;
化简乘法式子
tran : (r+1)*segment [l,r] a[i]  - segment  [l,r] i*a[i] ;
用树状数组维护即可;
*/

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn=2e5+7;
ll s[2][maxn],n,a[maxn],m;
ll lowbit(ll x){ return x&(-x);}
void update(ll pos,ll val,ll l){
    while(pos<=n){
        s[l][pos]-=val;
        pos+=lowbit(pos);
    }
}
ll sum(ll x,ll l){
    ll ans=0;
    while(x){
        ans+=s[l][x];
        x-=lowbit(x);
    }
    return ans;
}
int main(){
    ll k,l,r;
    scanf("%lld %lld",&n,&m);
    for(ll i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        update(i,-(a[i]*(n-i+1)),0);
        update(i,-a[i],1);
    }
    while(m--){
        scanf("%lld %lld %lld",&k,&l,&r);
        if(k==1){//区间求和
            ll ans=(sum(r,0)-sum(l-1,0))-((n-r)*(sum(r,1)-sum(l-1,1)));
            printf("%lld\n",ans);
        }
        else{//单点更新
            ll now=a[l]-r; a[l]=r;
            update(l,now*(n-l+1),0);update(l,now,1);
        }
    }
    return 0;
}
/**
I. Characters with Hash
链接:https://nanti.jisuanke.com/t/31461
题意:给定字符串每一个字符与给定字符相减后组成的新数字的长度;
****tricks****
每次相减后必须保持减数长度为 当前保持长度为2;
*/

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main (){
	int t;scanf("%d",&t);
	while(t--){
		int n;char ch;cin>>n>>ch;
		string str;cin>>str;
		int ans=0,flag=1;
		for(int i=0;i<n;i++){
			if(abs(str[i]-ch)==0&&flag) continue;
			else if(flag&&abs(str[i]-ch)!=0) ans+=log10(abs(str[i]-ch))+1,flag=0;
			else if(!flag) ans+=2;
		}
		if(ans==0) ans++;cout<<ans<<endl;
	}
	return 0;
}
/**
G. Trace
链接:https://nanti.jisuanke.com/t/31459
题意:依次给定一些点 每个点和原点(0,0)构成一个矩形 并标注在图上;
下个矩形更新时,会覆盖之前存在于当前矩形内的线段;
细节可以看图  问:更新完所有的点之后 所得到图形的周长;
set+二分
*/

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxn=1e5+7;
int  x[maxn],y[maxn];
set<int>s1,s2;
int tmp;
int main (){
    int n;scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d %d",&x[i],&y[i]);
    s1.insert(0),s2.insert(0);
    ll ans=0;
    for(int i=n-1;i>=0;i--){
        if(i==n-1) {
            ans+=x[i]+y[i];
            s1.insert(x[i]),s2.insert(y[i]);
        }
        else {
            auto it=s1.lower_bound(x[i]);
            ans+=x[i]-*--it;
            s1.insert(x[i]);
            it=s2.lower_bound(y[i]);
            ans+=y[i]-*--it;
            s2.insert(y[i]);
        }
    }
    printf("%lld\n",ans);
    return 0;
}
/**
 F. Features Track
链接:https://nanti.jisuanke.com/t/31458
题意:找最长的连续的<a,b>对;可用ma直接进行模拟最值即可;
一个记录最长的长度 一个记录是否连续即可;
*/

#include<bits/stdc++.h>
using namespace std;
map<pair<int,int>,int > mp1,mp2;

int main(){
    int t,n,maxn,k,x,y;
    scanf("%d",&t);
    while(t--){
        maxn=0;
        scanf("%d",&n);
        mp1.clear(),mp2.clear();
        for(int i=1;i<=n;i++){
            scanf("%d",&k);
            for(int j=1;j<=k;j++){
                scanf("%d %d",&x,&y);
                if(mp2[make_pair(x,y)]==i) continue;
                else if(mp2[make_pair(x,y)]==0||mp2[make_pair(x,y)]==i-1){
                    mp2[make_pair(x,y)]=i;
                    mp1[make_pair(x,y)]++;
                }
                else{
                    mp2[make_pair(x,y)]=i;
                    mp1[make_pair(x,y)]=1;
                }
                maxn=max(maxn,mp1[make_pair(x,y)]);
            }
        }
        printf("%d\n",maxn<2?0:maxn);
    }
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值