2018 icpc 青岛

https://zoj.pintia.cn/contests/91827364639/problems

C

要把这两个二进制串变为相同,需要先看哪些位置不同,设为数组c,某位为1则两位不同。

分1形成两段、四段或者更多段来考虑。

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <set>
#include <cmath>
#include <queue>
#include <map>
#define ll long long
#define ld double
#define lson rt << 1, l, m
#define pi acos(-1)
#define rson rt << 1 | 1, m + 1, r
#define fo(i, l, r) for (long long i = l; i <= r; i++)
#define fd(i, l, r) for (long long i = r; i >= l; i--)
#define mem(x) memset(x, 0, sizeof(x))
#define eps 1e-10
using namespace std;
const ll maxn = 1000050;
const ll mod = 998244353;
ll read()
{
    ll x = 0, f = 1;
    char ch = getchar();
    while (!(ch >= '0' && ch <= '9'))
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    };
    while (ch >= '0' && ch <= '9')
    {
        x = x * 10 + (ch - '0');
        ch = getchar();
    };
    return x * f;
}
int n,m;
char s[maxn],t[maxn];
int pt[10];
ll ans;
int main()
{

    int T;
    T = read();
    int tt = 0;
    while (T--)
    {
        ans=0;
        n=read();
        scanf("%s",s+1);
        scanf("%s",t+1);
        fo(i,1,n){
            s[i]-='0';
            t[i]-='0';
            s[i] ^= t[i];
        }
        int cnt = 0;
        fo(i,1,n){
            if(s[i]&&!s[i-1]){
                pt[++cnt]=i;
            }
            if(s[i]&&!s[i+1]){
                pt[++cnt]=i;
            }
            if(cnt>4)break;
        }
        if(cnt>4){
            printf("0\n");
            continue;
        }
        if(cnt==0){
            ans=(ll)n*(n+1)/2;
        }
        if(cnt==2){
            ans=n+n-2;
        }
        if(cnt==4){
            ans=6;
        }
        printf("%d\n",ans);

    }

    return 0;
}

M

递归,碰到循环节就停止。

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <set>
#include <cmath>
#include <queue>
#include <map>
#define ll long long
#define ld double
#define lson rt << 1, l, m
#define pi acos(-1)
#define rson rt << 1 | 1, m + 1, r
#define fo(i, l, r) for (long long i = l; i <= r; i++)
#define fd(i, l, r) for (long long i = r; i >= l; i--)
#define mem(x) memset(x, 0, sizeof(x))
#define eps 1e-10
using namespace std;
const ll maxn = 1050;
const ll mod = 998244353;
ll read()
{
    ll x = 0, f = 1;
    char ch = getchar();
    while (!(ch >= '0' && ch <= '9'))
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    };
    while (ch >= '0' && ch <= '9')
    {
        x = x * 10 + (ch - '0');
        ch = getchar();
    };
    return x * f;
}
ll x,k;
ll f[10] = {1,0,0,0,1,0,1,0,2,1};
ll g(int d,ll x){
    if(d==0) return x;
    if(x==1||x==0){
        return x^(d&1);
    }
    ll ret = 0;
    while(x){
        ret += f[x%10];
        x /= 10;
    }
    return g(d-1,ret);
}
int main()
{

    int T;
    T = read();
    int tt = 0;
    while (T--)
    {
        x=read();k=read();
        printf("%lld\n",g(k,x));   
    }
    return 0;
}

J

正好买m本书,还要带的钱最多。

考虑到,如果跳过若干本书,买一本,那把后一本书换成一开始跳过的书,答案会增加。

即,不存在这样的情况,买的书肯定是从1开始到m。

这个时候答案依然可能增加,要保证之后买不了书,就是加上之后价格最小的那本书-1

再判断一些特殊情况就可以。

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <set>
#include <cmath>
#include <queue>
#include <map>
#define ll long long
#define ld double
#define lson rt << 1, l, m
#define pi acos(-1)
#define rson rt << 1 | 1, m + 1, r
#define fo(i, l, r) for (long long i = l; i <= r; i++)
#define fd(i, l, r) for (long long i = r; i >= l; i--)
#define mem(x) memset(x, 0, sizeof(x))
#define eps 1e-10
using namespace std;
const ll maxn = 100050;
const ll mod = 998244353;
ll read()
{
    ll x = 0, f = 1;
    char ch = getchar();
    while (!(ch >= '0' && ch <= '9'))
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    };
    while (ch >= '0' && ch <= '9')
    {
        x = x * 10 + (ch - '0');
        ch = getchar();
    };
    return x * f;
}
int n,m;
ll a[maxn],ans;
int main()
{

    int T;
    T = read();
    int tt = 0;
    while (T--)
    {
        ans=0;
        n=read();m=read();
        fo(i,1,n){
            a[i]=read();
            if(!a[i]){
                i--;
                n--;
                m--;
            }
        }
        if(m<0||m>n){
            printf("Impossible\n");
            continue;
        }
        if(m==n){
            printf("Richman\n");
            continue;
        }
        fo(i,1,m){
            ans += a[i];
        }
        ll mn = 1e10;
        fo(i,m+1,n){
            mn = min(mn,a[i]);
        }
        mn--;
        ans+=mn;
        printf("%lld\n",ans);
    }

    return 0;
}

E

试着将操作进行分解,前进n次,倒退n次,把这些操作全部换成前进1次,倒退1次的操作,答案不会变劣。

首先二分,检验的时候,不断往前走,如果某个时刻发现前一个点不能满足要求,就在这两个点之间反复的跳,注意考虑最后一个点的情况。

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <set>
#include <cmath>
#include <queue>
#include <map>
#define ll long long
#define ld double
#define lson rt << 1, l, m
#define pi acos(-1)
#define rson rt << 1 | 1, m + 1, r
#define fo(i, l, r) for (long long i = l; i <= r; i++)
#define fd(i, l, r) for (long long i = r; i >= l; i--)
#define mem(x) memset(x, 0, sizeof(x))
#define eps 1e-10
using namespace std;
const ll maxn = 100050;
const ll mod = 998244353;
ll read()
{
    ll x = 0, f = 1;
    char ch = getchar();
    while (!(ch >= '0' && ch <= '9'))
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    };
    while (ch >= '0' && ch <= '9')
    {
        x = x * 10 + (ch - '0');
        ch = getchar();
    };
    return x * f;
}
ll a[maxn],b[maxn],c[maxn];
ll n,m,mx;
bool check(ll t){
    int nown = n;
    fo(i,1,n){
        b[i]=t/a[i];
        if(b[i]*a[i]<t)b[i]++;
    }
    b[n+1]=0;
    while(nown>=1&&b[nown]==0)nown--;
    fo(i,1,nown+1){
        if(i<=n)c[i]=1;
        else c[i]=0;
        if(b[i-1]>c[i-1]){
            c[i] += b[i-1]-c[i-1];
            c[i-1]=b[i-1];
        }
        if(i==n&&c[i]>b[i])c[i]--;

    }
    ll ret = 0;
    fo(i,1,nown+1){
        ret += c[i];
        if(ret > m) return false;
    }
    return true;
}
int main()
{

    int T;
    T = read();
    int tt = 0;
    while (T--)
    {
        n=read();m=read();
        mx=0;
        fo(i,1,n){
            a[i]=read();
            mx=max(mx,a[i]);
        }
        ll lp = 0,rp = mx*m,mid,ans=0;
        while(lp<=rp){
            mid = (lp + rp) >> 1;
            if(check(mid)){
                ans = mid;
                lp = mid + 1;
            }else{
                rp = mid - 1;
            }
        }
        printf("%lld\n",ans);
    }

    return 0;
}

F

首先,n个人最多打n-1轮,奇数个人不能打。

2、4个人都能打,然后发现6个人连两轮都打不了。

一开始是 2 1 4 3 6 5,假如说之后1个3打,按照只能要求1 2 3 4之间有比赛,5还是只能跟6打,因为第二轮与人的序号无关,这时候怎么调整都是徒劳。

人数是2^n的时候比较好安排,轮换一下就可以。

人数不是2^n的时候,还是按照2^n的情况排个表,因为之前就是保证字典序最小,所以编号大的都尽量出现在后面,如果这个时候表中出现了不得不跟一个不存在的大号打的情况,这个时候就安排不了了。

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include <set>
#include <queue>
#define ll long long
#define ld long double
#define lson l,m,rt<<1
#define pi acos(-1)
#define rson m+1,r,rt<<1|1
#define fo(i,l,r) for(int i = l;i <= r;i++)
#define fd(i,l,r) for(int i = r;i >= l;i--)
#define mem(x) memset(x,0,sizeof(x))
#define eps 3e-11
using namespace std;
const int maxn = 200050;
const ll inf = 1e9;
const ll mod = 998244353;
ll read() {
    ll x=0,f=1;
    char ch=getchar();
    while(!(ch>='0'&&ch<='9')) {
        if(ch=='-')f=-1;
        ch=getchar();
    };
    while(ch>='0'&&ch<='9') {
        x=x*10+(ch-'0');
        ch=getchar();
    };
    return x*f;
}
int n,k;
int a[2050][2050];
int main() {
    a[1][1]=a[2][2]=1;
    a[1][2]=a[2][1]=2;
    for(int t = 2;t <= 1024;t <<= 1){
        fo(i,1,t){
            fo(j,1,t){
                a[t+i][t+j] = a[i][j];
                a[t+i][j] = a[i][t+j] = a[i][j] + t;
            }
        }
    }
    int T=read();
    while(T--){
        n=read();k=read();
        if((n&1)||k>=n){
            puts("Impossible");
            continue;
        }
        bool flag = false;
        fo(i,1,k){
            fo(j,1,n){
                if(a[i+1][j] > n)flag=true;
            }
        }
        if(flag){
            puts("Impossible");
            continue;
        }
        fo(i,1,k){
            fo(j,1,n){
                printf("%d",a[i+1][j]);
                putchar(j==n?'\n':' ');
            }
        }
    }
    return 0;
}

D

枚举两个数的第一位,之后所有的位都确定了。

注意两位数不能有前导零,每一位的范围不能超。

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include <set>
#include <queue>
#define ll long long
#define ld long double
#define lson l,m,rt<<1
#define pi acos(-1)
#define rson m+1,r,rt<<1|1
#define fo(i,l,r) for(int i = l;i <= r;i++)
#define fd(i,l,r) for(int i = r;i >= l;i--)
#define mem(x) memset(x,0,sizeof(x))
#define eps 3e-11
using namespace std;
const int maxn = 400050;
const ll inf = 1e9;
const ll mod = 998244353;
ll read() {
    ll x=0,f=1;
    char ch=getchar();
    while(!(ch>='0'&&ch<='9')) {
        if(ch=='-')f=-1;
        ch=getchar();
    };
    while(ch>='0'&&ch<='9') {
        x=x*10+(ch-'0');
        ch=getchar();
    };
    return x*f;
}
ll n,m,len;
char s[maxn];
int a[maxn],b[maxn];
bool flag;
inline int check(int u,int v,int t){
    if(a[u]*b[v]==s[t])return 1;
    if(t<len&&s[t]&&(s[t]*10+s[t+1])==a[u]*b[v]) return 2;
    return 0;
}
inline int dv(int v,int t){
    if(s[t]%v==0) return s[t]/v;
    if(t<len&&(s[t]*10+s[t+1])%v==0) return (s[t]*10+s[t+1])/v;
    return -1;
}
bool check(int st){
    int t = st,u=1,v=1,sgn;
    while(t<=len){
        v++;
        if(v>m){
            v=1;
            u++;
        }
        if(u>n)break;
        if(u==1){
            b[v]=dv(a[u],t);
            if(b[v]==-1||b[v]>=10)return false;
        }else if(v==1){
            a[u] = dv(b[v],t);
            if(a[u]==-1||a[u]>=10)return false;
        }else{
            sgn=check(u,v,t);
            if(!sgn)return false;
        }
        t++;
        if(a[u]*b[v]>=10)t++;
    }
    return u==n&&v==m&&t==len+1;
}
bool gao(){
    int sgn;
    fo(i,1,9){
        fo(j,1,9){
           a[1]=i;b[1]=j;
           sgn=check(1,1,1);
           if(!sgn)continue;
           if(check(sgn+1))return true;
        }
    }
    return false;
}
int main() {
    int T=read();
    while(T--){
        flag=false;
        n=read();m=read();
        scanf("%s",s+1);
        len = strlen(s+1);
        if(n*m>len||n*m*2<len){
            puts("Impossible");
            continue;
        }
        fo(i,1,len)  s[i]-='0';
        if(gao()){
            fo(i,1,n){
                putchar('0'+a[i]);
            }
            putchar(' ');
            fo(i,1,m){
                putchar('0'+b[i]);
            }
            putchar('\n');
        }else{
            puts("Impossible");
        }
    }
    return 0;
}

 

posted @ 2019-10-12 01:34  ACforever  阅读(416)  评论(0编辑  收藏  举报