zoukankan      html  css  js  c++  java
  • 2021牛客寒假算法基础集训营6 ACDFGIJ

    A. 回文括号序列计数

    坑比题...注意回文的定义,并不是括号序列对称。比如(())不是回文的而))是回文的。而合法括号列左右两端一定是(和),必然非回文,因此只有空串答案是1.

    #include <iostream>
    using namespace std;
    #define mod 998244353
    int n;
    int main()
    {
    	//freopen("data.txt", "r", stdin);
    	int t;
    	cin >> t;
    	while(t--)
    	{
    		cin >> n;
    		if(!n) cout << 1 << endl;
    		else cout << 0 << endl;
    	}
    	return 0;
    }
    

    C. 末三位

    快速幂会t,因此可以找规律。

    证明详见https://blog.nowcoder.net/n/caa12c854288451a9bf1288a291a8e15

    #include <iostream>
    using namespace std;
    int n;
    int main()
    {
    	freopen("data.txt", "r", stdin);
    	while(cin >> n)
    	{
    		if(n == 0) cout << "001" << endl;
    		else if(n == 1) cout << "005" << endl;
    		else if(n == 2) cout << "025" << endl;
    		else if(n == 3) cout << "125" << endl;
    		else if(n == 4) cout << "625" << endl;
    		else if(n & 1) cout << "125" << endl;
    		else cout << "625" << endl;
    	}
    	return 0;
    }
    

    D. 划数

    “已知其中一个数cnt(cnt >= 11)”,而两数相加对11取模后肯定小于11,因此这肯定是数列的一个原本的数,那么剩下另一个数就是原来序列其他数的和。根据取模运算律直接计算即可。注意n = 2要特判。

    #include <iostream>
    #include <queue>
    #include <cstring>
    using namespace std;
    int n, cnt, a[150005], sum = 0;
    int main()
    {
    	freopen("data.txt", "r", stdin);
    	while(cin >> n >> cnt)
    	{
    		sum = 0;
    		for(int i = 1; i <= n; i++)
    		{
    			cin >> a[i];
    			sum = (sum + a[i]) % 11;
    		}
    		if(n == 2)
    		{
    			if(cnt == a[1]) cout << a[2] << endl;
    			else cout << a[1] << endl;
    			continue;
    		}
    		cout << (sum - cnt % 11 + 11) % 11 << endl;//cnt >= 11 肯定是数列的一个数 那么输出的就是剩下部分的和
    	}
    	return 0;
    }
    

    F. 组合数问题

    打表找规律可以解决,发现每次都是2的次幂附近的数,这些数与最近的2的次幂作差的绝对值又恰好是等比数列...

    证明见官方题解https://ac.nowcoder.com/discuss/599236?type=101&order=0&pos=1&page=1&channel=-1&source_id=1或者大佬博客https://blog.nowcoder.net/n/4682f520b038471dab543ab91c197727。

    #include <iostream>
    #define p 998244353
    #define LL long long
    #define maxn 100005
    using namespace std;
    void extend_gcd(LL a,LL b,LL &x,LL &y){
        if(b==0){
            x=1,y=0;
            return;
        }
        extend_gcd(b,a%b,y,x);
        y-=a/b*x;
    }
    
    LL inv[maxn + 10];
    LL f[maxn+10];
    void init(){//阶乘及其逆元打表
        f[0]=1;
        for(int i=1;i<=maxn;i++){
            f[i]=f[i-1]*i%p;
        }
    
        LL x,y;
        extend_gcd(f[maxn],p,x,y);//先求出f[N]的逆元,再循环求出f[1~N-1]的逆元
        inv[maxn]=(x%p+p)%p;
        for(int i=maxn-1;i>=1;i--){
            inv[i]=inv[i+1]*(i+1)%p;
        }
    }
    
    LL C(LL n,LL m){
        if(n==m||m==0)return 1;
        return (f[n]*inv[m]%p*inv[n-m]%p)%p;
    }
    long long fpow(long long a, long long b)
    {
    	long long ans = 1;
    	for(; b; b >>= 1)
    	{
    		if(b & 1) ans = ans * a % p;
    		a = a * a % p;
    	}
    	return ans;
    }
    int main()
    {
    	//init();
    	// int n = 4;
    	// LL ans = 0;
    	// for(int i = 0; i <= n; i += 4)
    	// {
    	// 	ans = (ans + C(n * 1ll, i * 1ll)) % p;
    	// }
    	// cout << ans;
    	freopen("data.txt", "r", stdin);
    	long long n;
    	cin >> n;
    	cout << (fpow(2, n - 2) + p + ((n / 4) & 1 ? -1 : 1) * 2 * fpow(4, n / 4 - 1) % p) % p;
    	return 0;
    }
    

    G. 机器人

    全排列会t(因为没法剪枝),考虑贪心:

    两个机器人时:(a_1(a_2x+b_2)+b_1<a_2(a_1x+b_1)+b_2),可以推广到多个,因此按照这个策略排序后计算答案即可。

    答案会爆long long,因此用__int128存储(or 高精度 or 两个long long)

    #include <iostream>
    #include <algorithm>
    #include <map>
    #include <vector>
    using namespace std;
    int n;
    __int128 x;
    bool vis[25];
    long long ans = 0;
    struct robot
    {
    	long long a, b;
    } r[25];
    bool cmp(robot x, robot y)
    {
    	//return (x.a - 1) * 1.0 / x.b < (y.a - 1) * 1.0 / y.b;
    	return x.b + x.a * y.b < y.b + y.a * x.b;
    }
    char ibuf[1000050],*s=ibuf;
    
    inline __int128 read()
    {
        __int128 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;
    }
    
    inline void write(__int128 x)
    {
        if(x<0)
        {
            putchar('-');
            x=-x;
        }
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
    int main()
    {
    	freopen("data.txt", "r", stdin);
    	cin >> n;
    	x = read();
    	for(int i = 1; i <= n; i++)
    	{
    		cin >> r[i].a >> r[i].b;
    	}
    	sort(r + 1, r + n + 1, cmp);
    	for(int i = 1; i <= n; i++)
    	{
    		x = x * r[i].a + r[i].b;
    	}
    	write(x);
    	return 0;
    }
    

    I. 贪吃蛇

    注意到尾巴不缩回,实际上就是BFS.

    #include <iostream>
    #include <queue>
    #include <cstring>
    using namespace std;
    int n, m;
    char mmap[105][105];
    bool vis[105][105];
    struct node
    {
    	int x, y, len;
    };
    node s, t;
    int ans = 0x3f3f3f3f;
    int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
    void bfs()
    {
    	queue<node> q;
    	q.push(s);
    	while(q.size())
    	{
    		node now = q.front();
    		q.pop();
    		//cout << now.x << ' ' << now.y  << endl;
    		if(now.x == t.x && now.y == t.y)
    		{
    			ans = now.len;
    			break;
    		}
    		for(int i = 0; i < 4; i++)
    		{
    			int nx = now.x + dir[i][0], ny = now.y + dir[i][1];
    			if(!vis[nx][ny] && nx >= 1 && nx <= n && ny >= 1 && ny <= m)
    			{
    				vis[nx][ny] = 1;
    				node nxt;
    				nxt.x = nx, nxt.y = ny, nxt.len = now.len + 1;
    				q.push(nxt);
    			}
    		}
    	}
    }
    int main()
    {
    	//freopen("data.txt", "r", stdin);
    	memset(vis, 0, sizeof(vis));
    	cin >> n >> m;
    	cin >> s.x >> s.y >> t.x >> t.y;
    	s.len = 0;
    	for(int i = 1; i <= n; i++)
    	{
    		scanf("%s", mmap[i] + 1);
    	}
    	for(int i = 1; i <= n; i++)
    	{
    		for(int j = 1; j <= m; j++)
    		{
    			if(mmap[i][j] == '#')
    			{
    				vis[i][j] = 1;
    			}
    		}
    	}
    	vis[s.x][s.y] = 1;
    	bfs();
    	if(ans != 0x3f3f3f3f) cout << ans * 100;
    	else cout << -1;
    	return 0;
    }
    
    
    

    J. 天空之城

    观察到走过的路代价为0,就是裸的MST。

    #include <iostream>
    #include <algorithm>
    #include <map>
    #include <vector>
    using namespace std;
    #define mod 998244353
    int n, q, city = 0;
    struct edge
    {
    	int x, y, z;
    };
    bool cmp(edge a, edge b)
    {
    	return a.z < b.z;
    }
    int fa[5005];
    int get(int x)
    {
    	if(x == fa[x]) return x;
    	return fa[x] = get(fa[x]);
    }
    int main()
    {
    	//freopen("data.txt", "r", stdin);
    	while(cin >> n >> q)
    	{
    		vector<edge> v;
    		for(int i = 1; i <= n; i++) fa[i] = i;
    		map<string, int> mp;
    		city = 0;
    		string tmp;
    		cin >> tmp;
    		mp[tmp] = ++city;
    		int cnt = 0;
    		for(int i = 1; i <= q; i++)
    		{
    			string uu, vv;
    			int x, y, w;
    			cin >> uu >> vv >> w;
    			if(mp.find(uu) != mp.end())
    			{
    				x = mp[uu];
    			}
    			else x = mp[uu] = ++city;
    			if(mp.find(vv) != mp.end())
    			{
    				y = mp[vv];
    			}
    			else y = mp[vv] = ++city;
    			edge ee;
    			ee.x = x, ee.y = y, ee.z = w;
    			v.push_back(ee);
    		}
    		sort(v.begin(), v.end(), cmp);
    		long long ans = 0;
    		for(int i = 0; i < v.size(); i++)
    		{
    			if(cnt == n - 1) break;
    			int x = v[i].x, y = v[i].y;
    			int xx = get(x), yy = get(y);
    			if(xx == yy) continue;
    			ans += 1ll * v[i].z;
    			fa[xx] = yy;
    			cnt++;
    		}
    		if(cnt == n - 1) cout << ans << endl;
    		else cout << "No!" << endl;
    	}
    }
    
  • 相关阅读:
    uvm_misc——杂货铺(miscellaneous)
    23种设计模式及其应用场景
    Hadoop TextInputFormat源码分析
    java字符串替换函数高效实现
    hadoop HA 之 QJM
    中文分词词性对照表
    计算两个字符串编辑距离
    java 图片处理
    zookeeper数据迁移
    正则表达式
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/14443684.html
Copyright © 2011-2022 走看看