2019牛客国庆集训派对day4—xiangtan-2017

C Intersection
在这里插入图片描述
题意:给你两个数组,找出满足x,x是A数组和B数组的线性基分别能够异或表示出来的数。
首先高斯消元把 A 和 B 变成线性无关组。
之后就是求方程 ∑ ai xi = ∑ bj yj 的解数,再次高斯消元得到零
空间的维数 d,答案就是 2d.

#include <bits/stdc++.h>
#define MAX_INT  ((unsigned)(-1)>>1)
#define MIN_INT  (~MAX_INT)
#define db printf("where!\n");
using namespace std;
typedef unsigned long long ll;
const int maxn=5e5+5;
int read()
{
    int c=0;int flag=1;
    char s;
    while((s=getchar())>'9'||s<'0')if(s=='-')flag=-1;
    c=s-'0';
    while((s=getchar())<='9'&&s>='0') c=c*10+s-'0';
    return c*flag;
}
const int maxbit=64;
int n;
ll a[maxbit],b[maxbit],p1[maxbit],p2[maxbit];
bool inser(ll k,ll p[])
{//求线性基
    for(int i=maxbit-1;i>=0;i--){
        if((k>>i)&1){
            if(p[i]==0){
                p[i]=k;
                return 1;
            }
            else k^=p[i];
        }
    }
    return 0;
}
int main(void)
{
    while(cin>>n){
        memset(p1,0,sizeof p1);
        memset(p2,0,sizeof p2);
        for(int i=1;i<=n;i++) cin>>a[i];
        for(int i=1;i<=n;i++) cin>>b[i];
        for(int i=1;i<=n;i++) inser(a[i],p1);
        for(int i=1;i<=n;i++) inser(b[i],p2);
        ll ans=0;
        for(int i=maxbit-1;i>=0;i--){//看看这个 向量能不能被另一个给表达出来
            if(p1[i]&& !inser(p1[i],p2)) ans++;//能
        }
        cout<< (1ll<<ans) <<endl;
    }
    return 0;
}

D Super Resolution

题目描述
Bobo has an n×m picture consists of black and white pixels.
He loves the picture so he would like to scale it a×b times.
That is, to replace each pixel with a×b block of pixels with the same color (see the example for clarity).
输入描述:
The input contains zero or more test cases and is terminated by end-of-file. For each test case,

The first line contains four integers n, m, a, b.
The i-th of the following n lines contains a binary string of length m which denotes the i-th row of the original picture. Character “0” stands for a white pixel while the character “1” stands for black one.

  • n, m, a, b 1≤n,m,a,b≤10
  • The number of tests cases does not exceed 10.

输出描述:
For each case, output n×a rows and m×b columns which denote the result.

输入
复制
2 2 1 1
10
11
2 2 2 2
10
11
2 2 2 3
10
11
输出
复制
10
11
1100
1100
1111
1111
111000
111000
111111
111111

题意:看了案例就懂了,很简单的模拟题~

#include<bits/stdc++.h>
#define MAX_INT  ((unsigned)(-1)>>1)
#define MIN_INT  (~MAX_INT)
#define pi 3.1415926535898
#define ll long long
using namespace std;
int a,b,c,d;
char aa[15][15];
int main(void)
{
      while(cin>>a>>b>>c>>d){
            for(int i=1;i<=a;i++){
                  for(int j=1;j<=b;j++){
                        cin>>aa[i][j];
                  }
            }
            for(int i=1;i<=a;i++){
                  for(int i1=1;i1<=c;i1++){
                        for(int j=1;j<=b;j++){
                              for(int j1=1;j1<=d;j1++){
                                    cout<<aa[i][j];
                              }
                        }
                        cout<<endl;
                  }
            }
      }
      return 0;
}

E Partial Sum
在这里插入图片描述
|∑ rj=l+1 | a j = max{Sr- Sl, Sl - Sr},其中 Si = a1 + a2 + · · · + ai.
所以等价于选择 2m 个前缀和,其中 m 是正号,m 个是负号。
自然是最大的 m 作为正号,最小的 m 个作为负号。
只需要对前缀和排序,枚举 m 并更新答案。
//脑洞题

#include <bits/stdc++.h>
#define MAX_INT  ((unsigned)(-1)>>1)
#define MIN_INT  (~MAX_INT)
#define db printf("where!\n");
using namespace std;
#define ll long long
const int maxn=5e5+5;
int read()
{
    int c=0;int flag=1;
    char s;
    while((s=getchar())>'9'||s<'0')if(s=='-')flag=-1;
    c=s-'0';
    while((s=getchar())<='9'&&s>='0') c=c*10+s-'0';
    return c*flag;
}
ll num[100005];
int main(void)
{
    int n,m,c;
    while(cin>>n>>m>>c){
        //memset(num,0,sizeof num);//多了这个就超时了!!!
        ll a;
        for(int i=1;i<=n;i++){
            cin>>a;
            num[i]=num[i-1]+a;
        }
        sort(num,num+1+n);
        ll ans=0;
        int l=0,r=n;
        while(m--&&l<=r){
            if(abs(num[r]-num[l])<c) break;
            ans=ans+abs(num[r]-num[l])-c;
            r--;l++;
        }
        cout<<ans<<endl;
    }
    return 0;
}

H Highway

题目描述
In ICPCCamp there were n towns conveniently numbered with 1,2,…,n
connected with (n - 1) roads.
The i-th road connecting towns ai and bi has length ci .
It is guaranteed that any two cities reach each other using only roads.

Bobo would like to build (n - 1) highways so that any two towns reach each using only highways.
Building a highway between towns x and y costs him δ(x,y) cents,
where δ(x,y) is the length of the shortest path between towns x and y using roads.

As Bobo is rich, he would like to find the most expensive way to build the (n - 1) highways.
输入描述:
The input contains zero or more test cases and is terminated by end-of-file. For each test case:
在这里插入图片描述
输出描述:
For each test case, output an integer which denotes the result.

按照 Prim 算法计算生成树。
假设初始点 v0 是某条直径的端点。那么距离 v0 最远的 v1 必然
是直径的另一个端点。
又因为距离任意点最远的要么是 v0 要么是 v1,所以剩下的点只
需要连往 v0 和 v1 中较远的一个即可。

#include <bits/stdc++.h>
#define MAX_INT  ((unsigned)(-1)>>1)
#define MIN_INT  (~MAX_INT)
#define db printf("where!\n");
using namespace std;
#define ll long long
const int maxn=1e5+5;
int read()
{
    int c=0;int flag=1;
    char s;
    while((s=getchar())>'9'||s<'0')if(s=='-')flag=-1;
    c=s-'0';
    while((s=getchar())<='9'&&s>='0') c=c*10+s-'0';
    return c*flag;
}
int head[maxn],cnt,maxdot,n;
ll dis[maxn],ans,disdot1[maxn],disdot2[maxn];
bool vi[maxn];
struct Edge
{
    int u,v,w,next;
}edge[maxn<<1];
void add(int u,int v,int w)//构图
{
    edge[cnt].u=u;edge[cnt].w=w;edge[cnt].v=v;
    edge[cnt].next=head[u];head[u]=cnt++;
}
void bfs(int s)
{
    memset(vi,0,sizeof vi);
    memset(dis,0,sizeof dis);
    queue<int> q;
    ans=0;
    maxdot=0;
    q.push(s);vi[s]=1;
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].v;
            if(!vi[v]){
                if(dis[v]<dis[u]+(ll)edge[i].w){
                    dis[v]=dis[u]+(ll)edge[i].w;
                    vi[v]=1;
                    q.push(v);
                }
            }
        }
    }
    for(int i=1;i<=n;i++){
        if(ans<dis[i]) ans=dis[i],maxdot=i;
    }
}
int main(void)
{
    while(cin>>n){
        cnt=0;
        for(int i=1;i<=n;i++){
            head[i]=-1,disdot1[i]=0,disdot2[i]=0;
        }
        for(int i=1;i<n;i++){
            int u,v,w;cin>>u>>v>>w;
            add(u,v,w);add(v,u,w);
        }
        bfs(1);//找出其中一个直径端点
        bfs(maxdot);//找出另一个
        for(int i=1;i<=n;i++){//存一个
            disdot1[i]=dis[i];
        }
        bfs(maxdot);
        ll Max=ans;
        for(int i=1;i<=n;i++) disdot2[i]=dis[i];//存另一个
        ll res=0;
        for(int i=1;i<=n;i++) res+=max(disdot1[i],disdot2[i]);
        cout<<res-Max<<endl;
    }
    return 0;
}

I Strange Optimization
在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
#define MAX_INT  ((unsigned)(-1)>>1)
#define MIN_INT  (~MAX_INT)
#define pi 3.1415926535898
#define ll long long
using namespace std;
 
int main(void)
{
      ll a,b;
      while(cin>>a>>b){
            cout<<"1/"<<a/__gcd(a,b)*b*2<<endl;
      }
      return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值