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