CF1422

那个博客搭好遥遥无期。

A:

看代码就行。

#include<bits/stdc++.h>
using namespace std;
void work()
{
	int a,b,c;
	scanf("%d%d%d",&a,&b,&c);
	if(a < b)swap(a,b);
	if(a < c)swap(a,c);
	if(a >= b + c)printf("%d\n",a - b - c + 1);
	else puts("1");
	return;
}
int main()
{
	int testcases = 0;
	scanf("%d",&testcases);
	while(testcases--)work();
	return 0;
}

B:

四个对称位置必须相同,必须都改成中位数,还有中间那一行和那一列。

#include<bits/stdc++.h>
using namespace std;
int n,m;
#define MAXN 110
int a[MAXN][MAXN];
bool vis[MAXN][MAXN];
int s[5];
void work()
{
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= n;++i)for(int j = 1;j <= m;++j)scanf("%d",&a[i][j]);
	long long ans = 0;
	for(int i = 1;i <= n / 2;++i)
	{
		for(int j = 1;j <= m / 2;++j)
		{
			s[1] = a[i][j];s[2] = a[n - i + 1][j];s[3] = a[i][m - j + 1];s[4] = a[n - i + 1][m - j + 1];
			sort(s + 1,s + 1 + 4);
			ans += s[2] - s[1] + s[3] - s[2] + s[4] - s[2];
		}
	}
	if(n % 2 == 1)
	{
		for(int j = 1;j <= m / 2;++j)ans += abs(a[n / 2 + 1][j] - a[n / 2 + 1][m - j + 1]);
	}
	if(m % 2 == 1)
	{
		for(int i = 1;i <= n / 2;++i)ans += abs(a[i][m / 2 + 1] - a[n - i + 1][m / 2 + 1]);
	}
	cout << ans << endl;
	return;
}
int main()
{
	int testcases = 0;
	scanf("%d",&testcases);
	while(testcases--)work();
	return 0;
}

C:

推式子,就是几个等比数列求和。

#include<bits/stdc++.h>
using namespace std;
char c[100010];
int n;
int a[100010];
#define MOD 1000000007
int power(int a,int b)
{
	int res = 1;
	while(b > 0)
	{
		if(b & 1)res = 1ll * res * a % MOD;
		a = 1ll * a * a % MOD;
		b = b >> 1;
	}
	return res;
}
int inv(int k){return power(k,MOD - 2);}
int main()
{
	scanf("%s",c);
	n = strlen(c);
	for(int i = 0;i < n;++i)a[n - i] = c[i] - '0';
	int ans = 0;
	for(int k = 1;k <= n;++k)
	{
		ans = (ans + 1ll * a[k] * power(10,k - 1) % MOD * (1ll * (n - k + 1) * (n - k) / 2 % MOD) % MOD) % MOD;
		int sum1 = 0;
		int inv10 = power(10,MOD - 2);
		int sum = 1ll * inv10 * inv10 % MOD * (power(inv10,k - 1) - 1) % MOD * inv(inv10 - 1) % MOD;
		sum1 = 10ll * (1ll * inv10 * (k - 1) % MOD - sum + MOD) % MOD % MOD * a[k] % MOD * power(10,k - 1) % MOD * power(9,MOD - 2) % MOD;
		ans = (ans + sum1) % MOD;
	}
	cout << ans << endl;
	return 0;
}

D:

不妨把起点也看成传送门,那么最后一定是从一个传送门走到终点,可以发现,如果左右走,那么纵坐标是没影响的,因此每个传送门向他上下左右第一个传送门连边跑 \(dijkstra\) 就行了, \(O(n)\)

#include<bits/stdc++.h>
using namespace std;
int n,m;
#define MAXN 100010
int sx,sy,fx,fy;
struct pos{int x,y,id;}s[MAXN];
bool cmpx(pos a,pos b){return a.x < b.x;}
bool cmpy(pos a,pos b){return a.y < b.y;}
namespace DIJ
{
	struct edge{int to,nxt;long long v;}e[MAXN << 3];
	int edgenum = 0,lin[MAXN] = {0};
	void add(int a,int b,long long v){e[++edgenum] = (edge){b,lin[a],v};lin[a] = edgenum;return;}
	long long d[MAXN];
	bool vis[MAXN];
	long long dij(int s,int t)
	{
		memset(d,0x3f,sizeof(d));
		d[s] = 0;
		priority_queue< pair<long long,int> > q;
		q.push(make_pair(0,s));
		while(!q.empty())
		{
			int k = q.top().second;q.pop();
			if(vis[k])continue;
			vis[k] = true;
			for(int i = lin[k];i != 0;i = e[i].nxt)
			{
				if(d[e[i].to] > d[k] + e[i].v)
				{
					d[e[i].to] = d[k] + e[i].v;
					q.push(make_pair(-d[e[i].to],e[i].to));
				}
			}
		}
		return d[t];
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	scanf("%d%d%d%d",&sx,&sy,&fx,&fy);
	for(int i = 1;i <= m;++i)
	{
		scanf("%d%d",&s[i].x,&s[i].y);
		s[i].id = i;
	}
	++m;
	s[m] = (pos){sx,sy,m};
	for(int i = 1;i <= m;++i)DIJ::add(i,m + 1,abs(fx - s[i].x) + abs(fy - s[i].y));
	sort(s + 1,s + 1 + m,cmpx);
	for(int i = 1;i <= m;++i)
	{
		if(i - 1 >= 1)DIJ::add(s[i].id,s[i - 1].id,s[i].x - s[i - 1].x);
		if(i + 1 <= m)DIJ::add(s[i].id,s[i + 1].id,s[i + 1].x - s[i].x);
	}
	sort(s + 1,s + 1 + m,cmpy);
	for(int i = 1;i <= m;++i)
	{
		if(i - 1 >= 1)DIJ::add(s[i].id,s[i - 1].id,s[i].y - s[i - 1].y);
		if(i + 1 <= m)DIJ::add(s[i].id,s[i + 1].id,s[i + 1].y - s[i].y);
	}
	cout << DIJ::dij(m,m + 1) << endl;
	//for(int i = 1;i <= m + 1;++i)cout << DIJ::d[i] << " ";cout << endl;
	return 0;
}

E:

看了题解,一个有趣的 \(DP\)

如果 \(s[i]\ne s[i+1]\)\(dp[i]=s[i]+dp[i+1]\)

如果 \(s[i]=s[i+1]\)\(dp[i]=\min(s[i]+dp[i+1],dp[i+2])\)

字符串比较大小可以存储 \(2^x\) 长度的哈希值每次求 \(lcp\) 比较下一位。

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
#define MUL 19260817
#define MOD 998244353
int power[MAXN];
struct str{int c,nxt[18],hash[18],len;}s[MAXN];
int scnt = 0;
void build(str &ss,int ch,int nx)
{
	ss.c = ch;ss.nxt[0] = nx;ss.len = s[nx].len + 1;
	for(int i = 1;(1 << i) <= ss.len;++i)ss.nxt[i] = s[ss.nxt[i - 1]].nxt[i - 1];
	for(int i = 0;(1 << i) <= ss.len;++i)ss.hash[i] = ch;
	for(int i = 1;(1 << i) <= ss.len;++i)
		for(int j = 0,cur = nx;j < i;cur = s[cur].nxt[j],++j)
			ss.hash[i] = (1ll * ss.hash[i] * power[1 << j] % MOD + s[cur].hash[j]) % MOD;
	return;
}
bool strless(int a,int b)
{
	int lcp = 0,l = min(s[a].len,s[b].len);
	int cura = a,curb = b;
	for(int i = 17;i >= 0;--i)
		if(lcp + (1 << i) <= l && s[cura].hash[i] == s[curb].hash[i])
			lcp += (1 << i),cura = s[cura].nxt[i],curb = s[curb].nxt[i];
	if(lcp == s[a].len && lcp == s[b].len)return false;
	if(lcp == s[a].len)return true;
	if(lcp == s[b].len)return false;
	return s[cura].c < s[curb].c; 
}
int strmin(int a,int b){return strless(a,b) ? a : b;}
char ch[MAXN];
int n,dp[MAXN];
void print(int cur)
{
	int totl = s[cur].len;
	if(totl <= 10)
	{
		for(;cur != 0;cur = s[cur].nxt[0])putchar(s[cur].c);
	}
	else
	{
		for(int i = 1,curp = cur;i <= 5;++i,curp = s[curp].nxt[0])putchar(s[curp].c);
		printf("...");
		for(int i = 17,pos = totl - 2;i >= 0;--i)if(pos & (1 << i))cur = s[cur].nxt[i];
		putchar(s[cur].c);cur = s[cur].nxt[0];putchar(s[cur].c);
	}
	return;
}
int main()
{
	power[0] = 1;for(int i = 1;i < MAXN;++i)power[i] = 1ll * power[i - 1] * MUL % MOD;
	scanf("%s",ch + 1);n = strlen(ch + 1);
	for(int i = n;i >= 1;--i)
	{
		if(i + 1 <= n && ch[i] == ch[i + 1])
		{
			build(s[++scnt],ch[i],dp[i + 1]);
			dp[i] = strmin(scnt,dp[i + 2]);
		}
		else
		{
			build(s[++scnt],ch[i],dp[i + 1]);
			dp[i] = scnt;
		}
	}
	for(int i = 1;i <= n;++i)
	{
		printf("%d ",s[dp[i]].len);
		print(dp[i]);
		puts("");
	}
	return 0;
}

F:

对每个因子维护一个次数的单调栈,在每个位置存储这一个比栈里下一个多的那部分幂,那么对应区间乘积就是 \(\text{lcm}\) ,多次询问用主席树版本维护每个 \(r\) ,下标维护 \(l\) ,每次相当于是插入 \(a[r]\)

#include<bits/stdc++.h>
using namespace std;
int n;
#define MAX 200010
#define N 100010
bool isprime[MAX];
int prime[20010],mindiv[MAX],id[MAX];
int a[N];
#define MOD 1000000007
int power(int a,int b)
{
	int res = 1;
	while(b > 0)
	{
		if(b & 1)res = 1ll * res * a % MOD;
		a = 1ll * a * a % MOD;
		b = b >> 1;
	}
	return res;
}
int inv(int a){return power(a,MOD - 2);}
struct node{int lc,rc,mul;}t[N * 400];
int root[N],ptr = 0;
int newnode(){return ++ptr;}
#define mid ((l + r) >> 1)
void build(int &rt,int l,int r)
{
	rt = newnode();t[rt].mul = 1;
	if(l == r)return;
	build(t[rt].lc,l,mid);
	build(t[rt].rc,mid + 1,r);
	return;
}
void mul(int &rt,int p,int v,int l,int r)
{//if(l == 1 && r == n)cout << "mul " << p << " " << v << endl;
	int nrt = newnode();t[nrt] = t[rt];rt = nrt;
	if(l == r){t[rt].mul = 1ll * t[rt].mul * v % MOD;return;}
	if(p <= mid)mul(t[rt].lc,p,v,l,mid);
	if(p > mid)mul(t[rt].rc,p,v,mid + 1,r);
	t[rt].mul = 1ll * t[t[rt].lc].mul * t[t[rt].rc].mul % MOD;
	return;
}
int query(int rt,int L,int R,int l,int r)
{
	if(L <= l && r <= R)return t[rt].mul;
	int res = 1;
	if(L <= mid)res = 1ll * res * query(t[rt].lc,L,R,l,mid) % MOD;
	if(R > mid)res = 1ll * res * query(t[rt].rc,L,R,mid + 1,r) % MOD;
	return res;
}
struct fact{int tim,pos;};
stack<fact> s[20010];
void spop(int fac,int pos)
{
	int tim = s[id[fac]].top().tim;
	mul(root[pos],s[id[fac]].top().pos,inv(power(fac,tim)),1,n);
	s[id[fac]].pop();
	if(!s[id[fac]].empty())mul(root[pos],s[id[fac]].top().pos,power(fac,tim),1,n);
	return;
}
void spush(int fac,int tim,int pos)
{
	if(!s[id[fac]].empty())mul(root[pos],s[id[fac]].top().pos,inv(power(fac,tim)),1,n);
	s[id[fac]].push((fact){tim,pos});
	mul(root[pos],pos,power(fac,tim),1,n);
	return;
}
void insert(int fac,int tim,int pos)
{
	while(!s[id[fac]].empty() && tim >= s[id[fac]].top().tim)spop(fac,pos);
	spush(fac,tim,pos);
	return;
}
int query(int l,int r)
{
	return query(root[r],l,r,1,n);
}
int main()
{
	for(int i = 2;i < MAX;++i)isprime[i] = true;
	for(int i = 2;i < MAX;++i)
	{
		if(isprime[i])prime[++prime[0]] = i,mindiv[i] = i;
		for(int j = 1;j <= prime[0] && i * prime[j] < MAX;++j)
		{
			isprime[i * prime[j]] = false;
			mindiv[i * prime[j]] = prime[j];
			if(i % prime[j] == 0)break;
		}
	}
	for(int i = 1;i <= prime[0];++i)id[prime[i]] = i;
	scanf("%d",&n);
	for(int i = 1;i <= n;++i)scanf("%d",&a[i]);
	build(root[0],1,n);
	for(int i = 1;i <= n;++i)
	{//cout << " : " << i << endl;
		root[i] = root[i - 1];
		int val = a[i],last = 0,cnt = 0;
		while(val != 1)
		{
			if(mindiv[val] == last)++cnt;
			else
			{
				insert(last,cnt,i);
				last = mindiv[val];cnt = 1;
			}
			val /= mindiv[val];
		}
		insert(last,cnt,i);
	}
	int q,a,b,lastans = 0;
	scanf("%d",&q);
	for(int i = 1;i <= q;++i)
	{
		scanf("%d%d",&a,&b);
		a = (lastans + a) % n + 1;b = (lastans + b) % n + 1;
		if(a > b)swap(a,b);
		printf("%d\n",lastans = query(a,b));
	}
	return 0;
}
 posted on 2020-10-09 17:27  15101051  阅读(138)  评论(0编辑  收藏  举报