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; }