• CF1422


    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
    ",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] e 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:

    对每个因子维护一个次数的单调栈,在每个位置存储这一个比栈里下一个多的那部分幂,那么对应区间乘积就是 ( ext{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
    ",lastans = query(a,b));
    	}
    	return 0;
    }
    
  • 相关阅读:
    MarkDownPad2 注册码
    如何让你的.vue在sublime text 3 中变成彩色?
    字典树入门
    博弈论
    复杂度问题
    gets scanf以及缓冲区域的问题
    对象
    矩阵转置的一般算法
    二叉树的建立、遍历、叶子节点计数、深度计算
    D
  • 原文地址:https://www.cnblogs.com/wjh15101051/p/13786971.html
Copyright © 2020-2023  润新知