• 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
    ",&x,&y);
        while(sum<=x)
        {
            sum*=2;
        }
        sum--;
        printf("2
    ");
        printf("%lld %lld
    ",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
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    【java基础学习一】int[]、Integer[]、String[] 排序( 正序、倒叙)、去重
    【转】jqGrid 各种参数 详解
    CSS 中文字体的英文名称 (simhei, simsun) 宋体 微软雅黑
    Web应用程序项目XX已配置为使用IIS
    zsh安装及配置
    vscode安装及配置
    matlab2018a安装及配置
    teminator安装及配置
    clion安装及配置
    pcl之octree的使用
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/14355105.html
Copyright © 2020-2023  润新知