其他分享
首页 > 其他分享> > 2020ICPC济南站部分题解

2020ICPC济南站部分题解

作者:互联网

A题

看出独立性后高斯消元

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=205;
int a[N][N];//增广矩阵
int x[N];//解集
int freeX[N];//自由变元
int Gauss(int equ,int var){//返回自由变元个数
    /*初始化*/
    for(int i=0;i<=var;i++){
        x[i]=0;
        freeX[i]=0;
    }
 
    /*转换为阶梯阵*/
    int col=0;//当前处理的列
    int num=0;//自由变元的序号
    int row;//当前处理的行
    for(row=0;row<equ&&col<var;row++,col++){//枚举当前处理的行
        int maxRow=row;//当前列绝对值最大的行
        for(int i=row+1;i<equ;i++){//寻找当前列绝对值最大的行
            if(abs(a[i][col])>abs(a[maxRow][col]))
                maxRow=i;
        }
        if(maxRow!=row){//与第row行交换
            for(int j=row;j<var+1;j++)
                swap(a[row][j],a[maxRow][j]);
        }
        if(a[row][col]==0){//col列第row行以下全是0,处理当前行的下一列
            freeX[num++]=col;//记录自由变元
            row--;
            continue;
        }
 
        for(int i=row+1;i<equ;i++){
            if(a[i][col]!=0){
                for(int j=col;j<var+1;j++){//对于下面出现该列中有1的行,需要把1消掉
                    a[i][j]^=a[row][j];
                }
            }
        }
    }
 
    /*求解*/
    //无解:化简的增广阵中存在(0,0,...,a)这样的行,且a!=0
    for(int i=row;i<equ;i++)
        if(a[i][col]!=0)
            return -1;
 
    //无穷解: 在var*(var+1)的增广阵中出现(0,0,...,0)这样的行
    int temp=var-row;//自由变元有var-row个
    if(row<var)//返回自由变元数
        return temp;
 
    //唯一解: 在var*(var+1)的增广阵中形成严格的上三角阵
    for(int i=var-1;i>=0;i--){//计算解集
        x[i]=a[i][var];
        for(int j=i+1;j<var;j++)
            x[i]^=(a[i][j]&&x[j]);
    }
    return 0;
}
int A[N][N],B[N][N];
ll ksm(ll x,ll y,ll m){
    ll res=1;
    while(y){
        if(y&1)res=res*x%m;
        x=x*x%m;
        y>>=1;
    }
    return res;
}
int main(void)
{
    int n;scanf("%d",&n);
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++)scanf("%d",&A[i][j]);
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++)scanf("%d",&B[i][j]);
    }
    long long ean=0;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            for(int k=0;k<n;k++){
                if(j==k)a[j][j]=A[j][j]^B[j][i];
                else a[j][k]=A[j][k];
            }
        }
        int freeNum=Gauss(n,n);//获取自由元
        if(freeNum == -1) continue;
        else ean+=freeNum;
    }
    cout<<ksm(2ll,ean,1ll*998244353);
    return 0;
}
View Code

C题

答案和3无关,只要考虑1和2的相对大小求解即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=1e6+10;
ll a[N];
int main(){
    ios::sync_with_stdio(false);
    int i;
    ll ans=0;
    for(i=1;i<=3;i++){
        cin>>a[i];
    }
    if(a[1]>=a[2]){
        ans+=2*a[2];
        a[1]-=a[2];
        ans+=3*(a[1]/3);
        if(a[1]%3==2){
            ans+=1;
        }
        cout<<ans<<endl;
    }
    else{
        ans+=2*a[1];
        a[2]-=a[1];
        ans+=6*(a[2]/3);
        if(a[2]%3==2){
            ans+=4;
        }
        cout<<ans<<endl;
    }
    return 0;
}
View Code

D题

刚开始是全部取右边,因此我们排序后控制自己的位置不能小于前面一个人的位置,在这种情况下取最小

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=1e6+10;
int l[N],r[N];
struct node{
    int x,low;
    bool operator <(const node &t) const{
        if(x!=t.x)
            return x<t.x;
        return low>t.low;
    }
}s[N];
ll w[N];
int main(){
    ios::sync_with_stdio(false);
    int i;
    int n;
    cin>>n;
    for(i=1;i<=n;i++){
        cin>>l[i]>>r[i];
        s[i].x=r[i];
        s[i].low=l[i];
    }
    ll ans=0;
    for(i=1;i<=n;i++){
        ans+=s[i].x;
    }
    sort(s+1,s+1+n);
    int lst;
    for(i=1;i<=n;i++){
        int tmp=0;
        if(i==1){
            tmp=s[i].x-s[i].low;
            lst=s[i].low;
            ans-=tmp;
            continue;
        }
        if(s[i].x==s[i-1].x){
            tmp=min(s[i].x-s[i].low,s[i].x-lst);
        }
        else{
            tmp=min(s[i].x-s[i].low,s[i].x-lst);
        }
        ans-=tmp;
        lst=s[i].x-tmp;
    }
    cout<<ans<<endl;
    return 0;
}
View Code

G题

签到题

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

int main(){
    LL x,y;
    LL sum=1;
    scanf("%lld %lld\n",&x,&y);
    while(sum<=x)
    {
        sum*=2;
    }
    sum--;
    printf("2\n");
    printf("%lld %lld\n",sum^x,sum^y);
    return 0;
}
View Code

L题

数位dp,观察求的是1的个数,而一个进位会影响到前面连续的1,因此我们要保留连续1的奇偶性,并且要保留全部1的奇偶性,但是这样还是没法,数据量依旧大

这个时候我们发发现因为m很小,所以只需要后7位就能记录所有相加的可能性,而只产生一个进位,因此对于后7位暴力计算,而只保留第七位往前的信息,这样复杂度就能过了

这样只会计算64*128*2*2*2左右的状态

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,int> pll;
const int N=1e6+10;
const ll mod=998244353;
ll f[65][128][2][2][2];
ll m,n;
int s[100],cnt;
int a[N];
int cal(int sta,int pre,int tot){
    int res=1;
    for(int i=0;i<m;i++){
        if(sta+i<128){
            res&=((__builtin_parity(sta+i)^tot)==a[i]);
        }
        else{
            res&=((__builtin_parity(sta+i)^pre^tot)==a[i]);
        }
    }
    return res;
}
ll dfs(int u,int sta,int sign,int pre,int tot){
    if(u==-1)
        return cal(sta,pre,tot);
    auto &x=f[u][sta][sign][pre][tot];
    if(x!=-1)
        return x;
    int up=1;
    if(sign)
        up=s[u];
    ll res=0;
    for(int i=0;i<=up;i++){
        if(u>6){
            res+=dfs(u-1,(sta*2+i)&127,sign&&(i==up),i&(!pre),tot^i);
        }
        else{
            res+=dfs(u-1,(sta*2+i)&127,sign&&(i==up),pre,tot);
        }
    }
    x=res;
    return x;
}
ll solve(ll n){
    cnt=0;
    memset(f,-1,sizeof f);
    if(n==0){
        s[cnt++]=0;
    }
    while(n){
        s[cnt++]=n&1;
        n/=2;
    }
    return dfs(cnt-1,0,1,0,0);
}
int main(){
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--){
        cin>>m>>n;
        for(int i=0;i<m;i++){
            cin>>a[i];
        }
        cout<<solve(n)<<endl;
    }
    return 0;
}
View Code

M题

签到题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=1e6+10;
int main(){
    ios::sync_with_stdio(false);
    int n,k;
    cin>>n>>k;
    if(n<=k){
        cout<<2<<endl;
        return 0;
    }
    n*=2;
    if(n%k){
        cout<<n/k+1<<endl;
    }
    else{
        cout<<n/k<<endl;
    }
    return 0;
}
View Code

 

标签:typedef,const,int,题解,ll,long,2020ICPC,include,济南
来源: https://www.cnblogs.com/ctyakwf/p/14355105.html