首页 > 其他分享 >The 2018 ICPC Asia Qingdao Regional Programming Contest (The 1st Universal Cup, Stage 9: Qingdao)

The 2018 ICPC Asia Qingdao Regional Programming Contest (The 1st Universal Cup, Stage 9: Qingdao)

时间:2024-04-27 17:22:07浏览次数:26  
标签:std CI include Contest int res Universal now Qingdao

Preface

久违地VP一场,虽然打的挺唐但勉强写出了8题

前中期EFB三开三卡属实有点难受,而且B题这个套路大合集我和徐神两个人写了快200行也占用了一定机时

但好在后面把卡住的题慢慢都写出来了,然后最后40min冲刺L题成功

比较可惜的是I这个开场看的题没有再细想一步,感觉想到在线段树上DP就很容易做了


A. Sequence and Sequence

防AK题,开场看了眼题面一眼不可做直接扔了


B. Kawa Exam

超级经典套路题,徐神1h就开了这道题然后开始写,后面我接力上去写了个DSU on Tree加线段树,这就是我们热血沸腾的组合技啊

首先原问题等价于,每个点有一个颜色,每个连通块的权值定义为其中出现次数最多的颜色的值

图的权值定义为所有连通块的权值和,现在要对于每一条边求出,断掉这条边后图的权值是多少

看到断边和连通性,很容易想到求出桥,显然不是桥的那些边删不删对答案没有影响,可以预先计算出

然后根据经典结论,将一个无向图边双缩点后,得到的一定是个森林,因此只要考虑在树上断一条边求解原问题

树上的断边又等价于选出一个子树,求出它的贡献以及删去整个子树后剩下部分的贡献

直接DSU on Tree扫描子树,同时线段树分别维护子树内和子树外每种颜色出现的次数即可,总复杂度\(O(n\log^2 n)\)

#include <bits/stdc++.h>

constexpr int $n = 200005;

std::vector<std::pair<int, int>> out[$n];

int dfn[$n], low[$n], tarjan_O;

std::vector<std::pair<int, int>> edge;
std::vector<bool> is_bridge;

int fa[$n];

bool vis[$n];

inline int father(int i) {
	if(fa[i] == i) return i;
	return fa[i] = father(fa[i]);
}

void tarjan(int u, int pre) {
	low[u] = dfn[u] = ++tarjan_O;
	vis[u] = true;
	int son = 0;
	int pre_cnt = 0;
	for(auto [v, id]: out[u]) {
		if(v == pre && pre_cnt == 0) { pre_cnt += 1; continue; }
		if(!dfn[v]) {
			son += 1;
			tarjan(v, u);
			if(low[u] > low[v]) low[u] = low[v];
			if(low[v] > dfn[u]) is_bridge[id] = true;
		} else if(low[u] > dfn[v]) {
				low[u] = dfn[v];
		}
	}
}
int n, m,C;
int a[$n], ans[$n], baseline;

std::vector<int> hkr[$n];
int ans_partial[$n];
std::map<int, int> rst[$n];
std::map<int, int> dfs1(int cur, int pre) {
	std::map<int, int> res {};
	vis[cur] = true;
	for(auto hkr: hkr[cur]) res[hkr] += 1;
	for(auto [ch, id]: out[cur]) if(ch != pre) {
		auto s = dfs1(ch, cur);
		if(s.size() > res.size()) std::swap(s, res);
		for(auto [k, v]: s) res[k] += v;
	}
	return res;
}
#define CI const int&

class Segment_Tree
{
	private:
		int mx[$n<<2];
	public:
		#define TN CI now=1,CI l=1,CI r=C
		#define LS now<<1,l,mid
		#define RS now<<1|1,mid+1,r
		inline void updata(CI pos,CI mv,TN)
		{
			if (l==r) return (void)(mx[now]+=mv); int mid=l+r>>1;
			if (pos<=mid) updata(pos,mv,LS); else updata(pos,mv,RS);
			mx[now]=std::max(mx[now<<1],mx[now<<1|1]);
		}
		inline int query(void)
		{
			return mx[1];
		}
		#undef TN
		#undef LS
		#undef RS
}IN,OUT;

int son[$n],sz[$n],bid[$n];
inline void getson(CI now,CI fa=0)
{
	sz[now]=1; son[now]=0; vis[now]=true;
	for (auto [to,_]:out[now]) if (to!=fa)
	{
		getson(to,now); sz[now]+=sz[to];
		if (sz[to]>sz[son[now]]) son[now]=to,bid[now]=_;
	}
}
inline void travel(CI now,CI fa,CI tp)
{
	for (auto x:hkr[now]) IN.updata(x,tp),OUT.updata(x,-tp);
	for (auto [to,_]:out[now]) if (to!=fa) travel(to,now,tp);
}
inline void DSU(CI outer,CI now,CI fa=0,CI id=-1,CI flag=0)
{
	for (auto [to,_]:out[now]) if (to!=fa&&to!=son[now]) DSU(outer,to,now,_,0);
	if (son[now]) DSU(outer,son[now],now,bid[now],1);
	for (auto [to,_]:out[now]) if (to!=fa&&to!=son[now]) travel(to,now,1);
	for (auto x:hkr[now]) IN.updata(x,1),OUT.updata(x,-1);
	if (~id) ans[id]=outer+IN.query()+OUT.query();
	if (!flag) travel(now,fa,-1);
}

void solve(CI outer,CI root) {
	for (auto [x,y]:rst[root]) OUT.updata(x,y);
	getson(root); DSU(outer,root);
	for (auto [x,y]:rst[root]) OUT.updata(x,-y);
}

#undef CI

void work() {
	std::cin >> n >> m; C=0; tarjan_O = 0;
	for(int i = 1; i <= n; ++i) low[i] = dfn[i] = 0;
	for(int i = 1; i <= n; ++i) std::cin >> a[i],C=std::max(C,a[i]);
	for(int i = 1; i <= n; ++i) out[i].clear();
	edge.resize(m), is_bridge.assign(m, false);
	for(int i = 0; i < m; ++i) {
		auto &[f, t] = edge[i];
		std::cin >> f >> t;
		out[f].emplace_back(t, i), out[t].emplace_back(f, i);
	}
	
	for(int i = 1; i <= n; ++i) vis[i] = false;
	
	for(int i = 1; i <= n; ++i) if(!vis[i]) tarjan(i, i);
	
//	for(int i = 0; i < m; ++i) if(is_bridge[i]) std::cerr << edge[i].first << " <-> " << edge[i].second << char(10);
//	std::cerr << "-------\n";
//	return ;
	
	for(int i = 1; i <= n; ++i) fa[i] = i;
	for(int i = 0; i < m; ++i) if(!is_bridge[i]) fa[father(edge[i].first)] = father(edge[i].second);
	for(int i = 1; i <= n; ++i) out[i].clear();
	
	std::set<std::pair<int, int>> edge_fuck;
	for(int i = 0; i < m; ++i) if(is_bridge[i]) {
		auto [_f, _t] = edge[i];
		int f = father(_f), t = father(_t);
		if(f > t) std::swap(f, t);
		if(edge_fuck.find({f, t}) != edge_fuck.end()) continue;
		edge_fuck.insert({f, t});
		out[f].emplace_back(t, i), out[t].emplace_back(f, i);
	}
	
	for(int i = 1; i <= n; ++i) hkr[i].clear();
	for(int i = 1; i <= n; ++i) hkr[father(i)].push_back(a[i]);
	
	baseline = 0;
	for(int i = 1; i <= n; ++i) vis[i] = false;
	for(int i = 1; i <= n; ++i) if(fa[i] == i && !vis[i]) {
		rst[i] = dfs1(i, i);
		ans_partial[i] = 0;
//		std::cerr << "i = " << i << char(10);
//		for(auto [k, v]: rst[i]) std::cerr << "k, v = " << k << ", " << v << char(10);
		for(auto [k, v]: rst[i]) if(v > ans_partial[i]) ans_partial[i] = v;
		baseline += ans_partial[i];
//		std::cerr << "ans_partial[" << i << "] = " << ans_partial[i] << char(10);
	} else rst[i].clear();
	
//	std::cerr << baseline << char(10);
//	std::cerr << "-------\n";
//	return ;
	
	for(int i = 1; i <= n; ++i) vis[i] = false;
	for(int i = 1; i <= n; ++i) if(fa[i] == i && !vis[i]) solve(baseline-ans_partial[i],i);

	for(int i = 0; i < m; ++i) is_bridge[i]
		? std::cout << ans[i] << char(i == m - 1 ? 10 : 32)
		: std::cout << baseline << char(i == m - 1 ? 10 : 32);
	return ;
}

int main() {
	// freopen("B.in","r",stdin);
	std::ios::sync_with_stdio(false);
	int T; std::cin >> T; while(T--) work();
	return 0;
}

C. Flippy Sequence

分类讨论题,找出两个串不同的极长区间的个数,记为\(cnt\),则:

  • \(cnt>2\),显然无解
  • \(cnt=2\),手玩以下会发现一定恰有\(6\)种方法,而且样例给出了这种情况所以很容易理解
  • \(cnt=1\),刚开始被坑了以为和区间长度有关,后面仔细想了下发现就是\(2\times (n-1)\)
  • \(cnt=0\),两次选的区间相同,方案数为\(\frac{n(n+1)}{2}\)
#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=1e6+5;
int t,n; char a[N],b[N];
int main()
{
	for (scanf("%d",&t);t;--t)
	{
		RI i; scanf("%d%s%s",&n,a+1,b+1);
		int cnt=0,lst=0;
		for (i=1;i<=n;++i) if (a[i]==b[i])
		{
			if (lst+1<=i-1) ++cnt; lst=i;
		}
		if (lst+1<=n) ++cnt;
		if (cnt>2) { puts("0"); continue; }
		if (cnt==2) { puts("6"); continue; }
		if (cnt==1) printf("%d\n",2*(n-1));
		else printf("%lld\n",1LL*n*(n+1)/2LL);
	}
	return 0;
}

D. Magic Multiplication

神秘模拟题,细节还是挺多的但想清楚还是很简单的

首先由于没有前导零,因此可以从\(1\sim 9\)枚举\(a_1\)的取值,当\(a_1\)确定时我们可以唯一确定出\(b_1\sim b_m\)的值

注意如果某个一位数\(x\)是\(a_1\)的倍数,那么对应的\(b_i\)必须是\(\frac{x}{a_1}\),否则如果在后面再加一个数得到的\(b_i\)一定是两位数

否则考虑取出两位来作为\(a_1\)和\(b_i\)的乘积,但要注意判掉前导零和得到的\(b_i>9\)的情况

现在我们已经得到了一组\(b_1\sim b_m\),然后就是用这些值来反着确定\(a_2\sim a_n\)的值了

注意当\(b_i=0\)时对应的\(a_i\)可以任意取值,因此有一些细节需要注意,最后如果回代检验成功就直接输出

具体细节可以看代码

#include<cstdio>
#include<iostream>
#include<cstring>
#define RI register int
#define CI const int&
using namespace std;
const int N=200005;
int t,n,m,a[N],b[N]; char s[N];
int main()
{
	for (scanf("%d",&t);t;--t)
	{
		RI i,j; scanf("%d%d%s",&n,&m,s+1);
		int len=strlen(s+1); bool flag=0;
		for (a[1]=1;a[1]<=9&&!flag;++a[1])
		{
			bool sign=1; int p=1;
			for (i=1;i<=m;++i)
			{
				if (p>len) { sign=0; break; }
				if ((s[p]-'0')%a[1]==0)
				{
					b[i]=(s[p]-'0')/a[1];
					++p; continue;
				}
				if (s[p]=='0') { sign=0; break; }
				if (p+1>len) { sign=0; break; }
				if (((s[p]-'0')*10+(s[p+1]-'0'))%a[1]==0)
				{
					b[i]=((s[p]-'0')*10+(s[p+1]-'0'))/a[1];
					if (b[i]>9) { sign=0; break; }
					p+=2; continue;
				}
				sign=0; break;
			}
			for (i=2;i<=n&&sign;++i)
			{
				a[i]=-1; for (j=1;j<=m;++j)
				{
					if (b[j]!=0)
					{
						if (p>len) { sign=0; break; }
						if ((s[p]-'0')%b[j]==0)
						{
							int tmp=(s[p]-'0')/b[j];
							if (tmp>9) { sign=0; break; }
							if (a[i]==-1) a[i]=tmp;
							else if (a[i]!=tmp) { sign=0; break; }
							++p; continue;
						}
						if (s[p]=='0') { sign=0; break; }
						if (p+1>len) { sign=0; break; }
						if (((s[p]-'0')*10+(s[p+1]-'0'))%b[j]==0)
						{
							int tmp=((s[p]-'0')*10+(s[p+1]-'0'))/b[j];
							if (tmp>9) { sign=0; break; }
							if (a[i]==-1) a[i]=tmp;
							else if (a[i]!=tmp) { sign=0; break; }
							p+=2; continue;
						}
					} else
					{
						if (p>len) { sign=0; break; }
						if (s[p]!='0') { sign=0; break; }
						++p; continue;
					}
				}
				if (a[i]==-1) a[i]=0;
			}
			if (sign&&p==len+1)
			{
				for (i=1;i<=n;++i) putchar(a[i]+'0'); putchar(' ');
				for (i=1;i<=m;++i) putchar(b[i]+'0'); putchar('\n');
				flag=1;
			}
		}
		if (!flag) puts("Impossible");
	}
	return 0;
}

E. Plants vs. Zombies

从开局搞到最后发现原来是爆long long了,真是经经又典典啊

首先最小值最大一眼二分答案,然后我们此时可以轻松确定出每个位置需要被走到的最少次数

考虑从前往后贪心处理,我们钦定处理到位置\(i\)时所有\(<i\)的位置已经满足要求了,那么要刷步数的话就直接在\((i,i+1)\)刷是最优的

总复杂度\(O(n\log Ans)\),注意潜在的爆long long问题

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

const int INF = (int)4e18+5;
const int N = 1e5+5;
int t, n, m, A[N], c[N];
bool check(int val){
//	printf("check(%lld)\n", val);
	for (int i=1; i<=n; ++i){
		c[i]=(val+A[i]-1)/A[i];
	}
	__int128 res=0;
	for (int i=1; i<=n; ++i){
		if (i<n || (n==i && c[i]>0)) ++res, --c[i];
		if (c[i]>0) c[i+1]-=c[i], res+=2*c[i], c[i]=0;
	}
//	printf("res=%lld\n", res);
	return res<=m;
}
signed main(){
	ios::sync_with_stdio(0); cin.tie(0);
	cin >> t;
	while (t--){
		cin >> n >> m;
		for (int i=1; i<=n; ++i) cin >> A[i];
		int L=0, R=INF;
		while (L<R){
			int M = L+(R-L)/2+1;
			if (check(M)) L=M;
			else R=M-1;
		}
		cout << L << '\n';
	}
	return 0;	
}

F. Tournament

神秘题,刚开始想漏了一个关键条件卡了我和徐神好久的时间,后面徐神上去写B我在下面冷静后发现好像是个找规律题

大力手玩会发现,当\(n\)为奇数时显然无解,\(2\mid n\and 4\nmid n\)时\(k\)至多为\(1\),这些都是很trivial的

然后画一画会发现\(n=8\)时可以达到\(n-1\)轮的上界,而\(n=12\)时最多就只能做\(3\)轮

索性大力猜测对于数\(n\)它能做到的最多轮次就是\(\operatorname{lowbit}(n)-1\),然后构造方案就直接异或就行

爬上去5min写了一发发现直接过了,我直接呃呃

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=1005;
int t,n,k;
int main()
{
	for (scanf("%d",&t);t;--t)
	{
		RI i,j; scanf("%d%d",&n,&k);
		auto lowbit=[&](CI x)
		{
			return x&-x;
		};
		if (k>lowbit(n)-1) { puts("Impossible"); continue; }
		for (i=1;i<=k;++i) for (j=0;j<n;++j) printf("%d%c",(j^i)+1," \n"[j==n-1]);
	}
	return 0;
}

G. Repair the Artwork

看过题人数还是挺可做的一个题,但赛时机时不够了只能作罢,之后有空再补吧


H. Mirror

没一个人过的几何,很符合我对几何的想象


I. Soldier Game

开场就看了这个题,然后一直摸到结束也不会,后面看了眼题解发现就是个傻逼题

首先这类极差问题的经典思路就是枚举确定最小值,然后在只考虑大于阈值的区间时能得到的最大值

这题虽然乍一看数据范围挺大,但仔细一想会发现合法的区间最多只有\(2n-1\)个,因此可以先排序然后枚举

现在问题就是怎么快速处理在ban掉部分区间的情况下用剩余区间覆盖\(1\sim n\),且最大权值最小

不妨考虑用线段树优化DP,在线段树\(x\)(对应区间\([l,r]\))的节点上维护\(f_{x,0/1,0/1}\),表示当覆盖区间\([l,r]\),且覆盖\(l\)位置的线段在/不在区间外,覆盖\(r\)位置的线段在/不在区间外的情形下,最小化的最大权值

转移的话也很trivial:

\[f_{x,p,q}=\min_{k\in \{0,1\}} \max(f_{ls(x),p,k},f_{rs(x),k,q}) \]

初始值的设置按照定义推一下也不难,然后每次删除一条线段就直接把线段树上对应的权值改成\(\infty\)即可

总复杂度\(O(n\log n)\)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<array>
#define int long long
#define RI register int
#define CI const int&
using namespace std;
const int N=100005,INF=1e18;
int t,n,a[N];
class Segment_Tree
{
	private:
		int f[N<<2][2][2];
		inline void pushup(CI now)
		{
			for (RI x=0;x<2;++x) for (RI y=0;y<2;++y)
			{
				f[now][x][y]=INF; for (RI k=0;k<2;++k)
				f[now][x][y]=min(f[now][x][y],max(f[now<<1][x][k],f[now<<1|1][k][y]));
			}
		}
	public:
		#define TN CI now=1,CI l=1,CI r=n
		#define LS now<<1,l,mid
		#define RS now<<1|1,mid+1,r
		inline void build(TN)
		{
			if (l==r)
			{
				f[now][0][0]=a[l]; f[now][0][1]=l<n?a[l]+a[l+1]:INF;
				f[now][1][0]=l>1?-INF:INF; f[now][1][1]=INF; return;
			}
			int mid=l+r>>1; build(LS); build(RS); pushup(now);
		}
		inline void modify(CI pos,CI len,TN)
		{
			if (l==r)
			{
				if (len==1) f[now][0][0]=INF; else f[now][0][1]=INF; return;
			}
			int mid=l+r>>1; if (pos<=mid) modify(pos,len,LS); else modify(pos,len,RS); pushup(now);
		}
		inline int query(void)
		{
			return f[1][0][0];
		}
		#undef TN
		#undef LS
		#undef RS
}SEG;
signed main()
{
	for (scanf("%lld",&t);t;--t)
	{
		RI i; for (scanf("%lld",&n),i=1;i<=n;++i) scanf("%lld",&a[i]);
		vector <array <int,3>> vec; SEG.build();
		for (i=1;i<=n;++i) vec.push_back({a[i],i,1});
		for (i=1;i<n;++i) vec.push_back({a[i]+a[i+1],i,2});
		sort(vec.begin(),vec.end()); int ans=INF;
		for (auto [val,p,len]:vec)
		ans=min(ans,SEG.query()-val),SEG.modify(p,len);
		printf("%lld\n",ans);
	}
	return 0;
}

J. Books

徐神开场写的,我题面都没看

#include <bits/stdc++.h>

using llsi = long long signed int;

void work() {
	int n, m;
	std::cin >> n >> m;
	std::vector<llsi> a(n);
	for(int i = 0; i < n; ++i) std::cin >> a[i];
	llsi ans = 0;
	int c0 = 0;
	for(int i = 0; i < n; ++i) c0 += !a[i];
	if(c0 > m) return void(std::cout << "Impossible\n");
	m -= c0;
	llsi sufmin = 1e17;
	for(int i = 0; i < n; ++i) if(a[i]) {
		if(m > 0) {
			ans += a[i];
			m -= 1;
		} else if(m == 0) {
			sufmin = std::min(sufmin, a[i] - 1);
		}
	}
	ans += sufmin;
	if(ans >= 1e17)
		std::cout << "Richman\n";
	else
		std::cout << ans << char(10);
}

int main() {
	std::ios::sync_with_stdio(false);
	int T; std::cin >> T;
	while(T--) work();
	return 0;
}

K. Airdrop

好像也是个可做题,但经典没时间了直接弃疗


L. Sub-cycle Graph

小清新计数题,稍微想一下就会了

首先先特判各种Corner Case,比如\(m>n\)时无解;\(m=n\)时为\(\frac{(n-1)!}{2}\)(不计方向的圆排列,所以要除以\(2\));\(m=0\)时为\(1\)

然后考虑一般的情况,不妨设度数为\(i\)的点的个数为\(d_i\),显然我们枚举\(d_1\)的值后就可以唯一确定\(d_0,d_2\)的值了

考虑现在图的形态,我们首先把编号划分给三种点,方案数为\(C_n^{d_0}\times C_{n-d_0}^{d_1}\),然后忽略掉所有的\(d_0\)

考虑先把\(d_1\)两两配对作为一条链的两个端点,这个的方案数是个经典问题

式子是\(C_{d_1}^{\frac{d_1}{2}}\times (\frac{d_1}{2})!\times \frac{1}{2^{\frac{d_1}{2}}}\),第一个组合数表示先定下一堆点放左边,然后剩下的点放在右边配对有阶乘种放法,但要注意因为后面加入的度数为\(2\)的点在中间的时候已经消除了顺序的影响,因此两端点顺序无关,每个pair都要除以\(2\)

最后插入度数为\(2\)的点可以这样考虑,先把\(d_2\)的点任意排列,然后再划分成\(\frac{d_1}{2}\)组,每组内元素连续

后者是个经典的插板法例题,因此再乘上\(d_2!\times C_{d_2+\frac{d_1}{2}-1}^{\frac{d_1}{2}}\)即可

#include <bits/stdc++.h>

using llsi = long long signed int;

constexpr llsi mod = 1'000'000'007;

constexpr llsi ksm(llsi a, llsi b) {
	llsi res = 1;
	while(b) {
		if(b & 1) res = res * a % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return res;
}

constexpr llsi inv2 = ksm(2, mod - 2);

llsi fac[1000006], facinv[1000006] , inv_pw2[1000006];

void prep_fac(llsi n = 1000000) {
	fac[0] = 1;
	for(llsi i = 1; i <= n; ++i) fac[i] = fac[i - 1] * i % mod;
	facinv[n] = ksm(fac[n], mod - 2);
	for(llsi i = n; i >= 0; --i) facinv[i - 1] = facinv[i] * i % mod;
	assert(facinv[0] == 1);
	inv_pw2[0] = 1; inv_pw2[1] = inv2;
	for(llsi i = 2; i <= n; ++i) inv_pw2[i] = inv_pw2[i - 1] * inv2 % mod;
	return ;
}

inline llsi C(llsi n, llsi m) {
	if(n < 0 || m < 0 || m > n) return 0;
	return fac[n] * facinv[m] % mod * facinv[n - m] % mod;
}

llsi work() {
	llsi n, m; std::cin >> n >> m;
	if(m > n) return 0;
	if(m == n) {
		if(n <= 2) return 0;
		return fac[n - 1] * inv2 % mod;
	}
	if(m == 0) return 1;
	llsi ans = 0;
	for(llsi d1 = 2; d1 <= n; d1 += 2) {
		const llsi d2 = (2 * m - d1) / 2;
		const llsi d0 = n - d1 - d2;
		if(d2 < 0 || d2 > n || d0 < 0 || d0 > n) continue;
		ans +=
			C(n, d0) * C(n - d0, d1) % mod * (
				C(d1, d1 / 2) * fac[d1 / 2] % mod
				* inv_pw2[d1 / 2] % mod
				* fac[d2] % mod
				* C(d2 + d1 / 2 - 1, d1 / 2 - 1) % mod) % mod;
	}
	
	return ans % mod;
}

int main() {
	std::ios::sync_with_stdio(false);
	prep_fac();
	int T; std::cin >> T; while(T--) std::cout << work() << char(10);
	return 0;
}

M. Function and Function

祁神开场写的签,我题都没看

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

int t, x, k;
const int tbl[10] = {1, 0, 0, 0, 1, 0, 1, 0, 2, 1};
int calc(int v){
	int res=0;
	while (v>0){
		res += tbl[v%10];
		v/=10;
	}
	return res;
}
signed main(){
	ios::sync_with_stdio(0); cin.tie(0);
	cin >> t;
	while (t--){
		cin >> x >> k;
		while (k>0 && x>0){
			--k;
			x = calc(x);	
		}
		if (k>0) cout << k%2 << '\n';
		else cout << x << '\n';
	}
	return 0;	
}

Postscript

晚上要上人工智能的实验课,而且明天要补五一的课,晚上有CF都懒得打

唉感觉最近训练量堪忧啊,好久没有打CF/ATC了的说

标签:std,CI,include,Contest,int,res,Universal,now,Qingdao
From: https://www.cnblogs.com/cjjsb/p/18162267

相关文章

  • The 2023 ICPC Asia Jinan Regional Contest
    目录写在前面DIAG写在最后写在前面比赛地址:https://codeforces.com/gym/104901。以下按个人向难度排序。SUA的题确实牛逼,把我这种只会套路的沙比狠狠腐乳了。D签到。直接枚举\([L,\min(R,L+10)]\)检查即可。///*By:Luckyblock*/#include<bits/stdc++.h>#defi......
  • RuntimeBroker.exe 是 Windows 操作系统中的一个系统进程,它负责管理 Metro 应用程序(现
    RuntimeBroker.exe是Windows操作系统中的一个系统进程,它负责管理Metro应用程序(现在称为UniversalWindowsPlatform应用程序)的权限和沙盒环境。该进程通常在用户登录后启动,并且对于每个用户会话都会有一个实例在运行。具体来说,RuntimeBroker主要有以下作用:权限管......
  • The 2022 ICPC Asia Xian Regional Contest / ICPC 西安 2022 (ABDHJKL)
    本文搬运自本人的知乎文章。https://zhuanlan.zhihu.com/p/588162564好久没有在补题之后写题解的习惯了。但是最近感觉有些题目的思路即使在题目通过后仍然难以理清,因此觉得需要写些东西帮助自己整理思路,另外也方便以后翻看积累到的技巧。J.StrangeSum题目链接Problem-J......
  • 2022 China Collegiate Programming Contest (CCPC) Mianyang | 2022 CCPC 绵阳(MAED
    搬运自本人知乎文章。https://zhuanlan.zhihu.com/p/588646549M.Rock-Paper-ScissorsPyramid题目链接Problem-M-Codeforces题意有一个长度为\(n\)的石头剪刀布序列,每个元素是RPS(石头、布、剪刀)中的一个,我们需要用这个序列构造一个三角,三角的底层为这个序列,第\(i(......
  • The 2022 ICPC Asia Xian Regional Contest
    The2022ICPCAsiaXianRegionalContestJ.StrangeSum题意:给定n个数,选定最多不超过两个数字的和的最大值思路:签到voidsolve(){lln;cin>>n;vector<ll>a(n+1);for(inti=1;i<=n;i++)cin>>a[i];llans=0;sort(a.begin()......
  • AtCoder Beginner Contest 350 A - G 题解
    AtCoderBeginnerContest350A-PastABCsSolution把最后三个字符转成数字判断即可Code#include<bits/stdc++.h>usingnamespacestd;intmain(){strings;cin>>s;s=s.substr(3,3);intx=0;x=(s[0]-'0')*100+(s[1]-�......
  • The 18-th Beihang University Collegiate Programming Contest (BCPC 2023) - Final
    https://codeforces.com/gym/104883A#include<bits/stdc++.h>usingnamespacestd;usingi32=int32_t;usingi64=longlong;usingvi=vector<int>;i32main(){ios::sync_with_stdio(false),cin.tie(nullptr);i64n,sum=0;c......
  • AtCoder Beginner Contest 350 G - Mediator
    链接:https://atcoder.jp/contests/abc350/tasks/abc350_g大致题意:给出n个点,q个询问1号询问要求u,v之前加一条无向边图始终是一个森林2号询问询问是否有一个点与u,v都相邻,若有则输出该点,若无则输出0。询问强制在线。思路:在题目要求的图中,满足2号询问的点只有三种情况:要么这个......
  • AtCoder Beginner Contest 350
    B-DentistAoki难度:⭐题目大意现在有数列1~n,现在有m次操作,每次给出一个x,如果x存在就是删去,不存在就加上;问最后数列还剩多少个;解题思路数据很小,暴力就行;神秘代码#include<bits/stdc++.h>#defineintlonglong#defineIOSios::sync_with_stdio......
  • AtCoder Beginner Contest 350
    A-PastABCs(abc350A)题目大意给定一个形如ABCXXX的字符串。问XXX是否是\(001\to349\)之间,且不能是\(316\)。解题思路将后三位转换成数字后判断即可。神奇的代码a=int(input().strip()[3:])ifa>=1anda<=349anda!=316:print("Yes")else:p......