• 2020hdu多校第三场比赛及补题


    1004 Tokitsukaze and Multiple

    队友半小时内A了这题,强的一匹!

    给一列数,每次可以把相邻的两个数合并成一个大数(比如12,74合并成86),给一个数字p,问通过这样的操作,最多能使这数列中多少数是p的倍数

    举例:p = 3, 数列为 2, 1, 3, 2, 1

    该数列可以变成3,3,3, 答案就是3

    这题我做的话半小时应该不能做出来

    可以用贪心的方法线性做,从左往右扫,每当判断出能合并出符合要求的数时就合并

    这个贪心和那个关于区间的贪心模板题很像

    事实上,这题假设我们已知所有能合成出符合要求的数的区间,问题就变成在这些区间里找出最多的互不重合的区间,那就是把这些区间按右端点排序

    队友这题写的代码并不是很美观,但还是很强的

    赛后我自己也做了一遍,下面的是我的代码

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    const int MAXN = 1e5+7;
    int a[MAXN], last[MAXN];
    int main()
    {
    	int T;
    	cin >> T;
    	int n,p,x;
    	while(T--){
    		cin>>n>>p;
    		int su = 0, pos = 1, ans = 0;
    		for(int i = 1;i < p;i++) last[i] = 0;
    		for(int i = 1;i <= n;i++){
    			scanf("%d",&x);
    			su += x;
    			su %= p;
    			if(su == 0 || last[su] >= pos){
    				pos = i + 1;
    				su = 0;
    				ans ++;
    			}
    			last[su] = i;
    		}
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    

      

    1005 Little W and Contest

    这里就不叙述题意了

    这题队友写的,队友写的很整齐,很美观

    但是wa了很多发,很惨

    比赛到后期的时候,队友叫我看这题,给了我题意和他的做法,我觉得他的做法没问题,代码也写的很好,查不出什么错,我找到一个地方可能有问题,就是一个取模的地方他是+MOD 再%MOD,我感觉+2*MOD再%MOD会更保险,然后队友改了下,还真就过了,队友气死了....

    我之后才学到一个更保险的办法是先%MOD,再+MOD,再%MOD

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    const int MAXN = 1e5 + 7;
    const int MOD = 1e9 + 7;
    
    int fac[MAXN], inv[MAXN];
    
    inline void Pre(int n)
    {
        fac[0] = 1;
        for (int i = 1; i <= n; i++)
            fac[i] = fac[i - 1] * i % MOD;
        inv[1] = 1;
        for (int i = 2; i <= n; i++)
            inv[i] = (MOD - MOD / i) * inv[MOD % i] % MOD;
        inv[0] = 1;
        for (int i = 1; i <= n; i++)
            inv[i] = inv[i] * inv[i - 1] % MOD;
    }
    
    inline int C(int n, int m)
    {
        if (m > n)
            return 0;
        return fac[n] * inv[m] % MOD * inv[n - m] % MOD;
    }
    // 计算组合数
    inline int Pow(int a, int b)
    {
        int ret = 1;
        for (; b; b >>= 1, a = a * a % MOD)
            if (b & 1)
                ret = ret * a % MOD;
        return ret;
    }
    // 快速幂
    
    int T;
    int n;
    int pts[MAXN];
    int u, v;
    int ans;
    int tmp1, tmp2;
    
    struct DSU
    {
        int parent[MAXN];
        int n; // Nums of Nodes
        int cnt; // Count Strongly Connected Components
        int sum1[MAXN];
        int sum2[MAXN];
        int rank[MAXN];
    
        void init_parent(int n)
        {
            this -> n = n;
            cnt = 0;
            for (int i = 1; i <= n; ++i)
            {
                parent[i] = i;
                if (pts[i] == 1)
                {
                    sum1[i] = 1;
                    sum2[i] = 0;
                }
                else
                {
                    sum1[i] = 0;
                    sum2[i] = 1;
                }
                rank[i] = 0;
            }
        }
    
        int find_parent(int x)
        {
            if (parent[x] == x)
                return x;
            else
                parent[x] = find_parent(parent[x]);
            return parent[x];
        }
    
        bool check_unicom(int x, int y)
        {
            return find_parent(x) == find_parent(y);
        }
    
        void merge(int x, int y)
        {
            x = find_parent(x);
            y = find_parent(y);
            if (x != y)
            {
                parent[x] = y;
                sum1[y] += sum1[x];
                sum2[y] += sum2[x];
                cnt++;
            }
        }
    
        int getsum1(int i)
        {
            return sum1[find_parent(i)];
        }
        int getsum2(int i)
        {
            return sum2[find_parent(i)];
        }
    }dsu;
    
    int32_t main(void)
    {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        Pre(100005);
        cin >> T;
        while (T--)
        {
            cin >> n;
            ans = 0;
            tmp1 = tmp2 = 0;
            for (int i = 1; i <= n; ++i)
            {
                cin >> pts[i];
                if (pts[i] == 1)
                {
                    tmp1++;
                }
                if (pts[i] == 2)
                {
                    tmp2++;
                }
            }
            dsu.init_parent(n);
            ans = (C(tmp2, 2) % MOD * tmp1 % MOD) % MOD + C(tmp2, 3) % MOD;
            ans %= MOD;
            cout << ans << endl;
            for (int i = 1; i <= n - 1; ++i)
            {
                cin >> u >> v;
                if (!dsu.check_unicom(u, v))
                {
                    int usum1 = dsu.getsum1(u);
                    int usum2 = dsu.getsum2(u);
                    int vsum1 = dsu.getsum1(v);
                    int vsum2 = dsu.getsum2(v);
                    // cout << usum1 << " " << usum2 << " " << vsum1 << " " << vsum2 << endl;
                    int les2 = tmp2 - usum2 - vsum2;
                    int les1 = tmp1 - usum1 - vsum1;
                    // cout << les1 << " " << les2 << endl;
                    ans = ans + 2 * MOD
                    - les2 * ((usum2 * vsum1) % MOD + (usum1 * vsum2) % MOD) % MOD 
                    - ((les2 + les1) % MOD) * (usum2 * vsum2 % MOD) % MOD
                    ;
                    dsu.merge(u, v);
                }
                ans %= MOD;
                cout << ans << endl;
            }
        }
        return 0;
    }
    

      

    队友喜欢把并查集写成结构体,我通常不这样做。

    1009 Parentheses Matching

    这场的签到题,括号匹配题

    括号匹配的栈模拟题我还挺怕的,所以我很早看了这题后就把这题先放了,把这题交给队友解决,自己想其他题,然而我什么也没想出来,队友也一直没做出这题,我还是得来写这题

    写了几遍才知道怎么写好

    因为是字典序最小,所以:

    缺 ( 时,要把最左边的 * 变成 (

    缺 ) 时,要把最右边的 * 变成 )

    #include<iostream>
    #include<algorithm>
    #include<stack>
    using namespace std;
    stack<char> st;
    char ans[100007];
    int main()
    {
    	int t;
    	string s,ans;
    	cin>>t;
    	while(t--){
    		cin>>s;
    		while(!st.empty()) st.pop();
    		int cnt1 = 0,cnt2 = 0;
    		bool flag = true;
    		for(int i = 0;s[i];i++){
    			if(s[i]=='*') cnt1++;
    			else if(s[i]=='(') st.push(s[i]);
    			else{
    				if(!st.empty()) st.pop();
    				else {
    					cnt2++;
    					if(cnt2 > cnt1) {
    						flag = false;
    						break;
    					}
    				}
    			} 
    		}
    		if(!flag) {
    			printf("No solution!\n");
    			continue;
    		}
    		else{
    			int cnt = 0;
    			for(int i = 0;s[i]&&cnt<cnt2;i++){
    				if(s[i]=='*') {
    					cnt++;
    					s[i] = '(';
    				}
    			}
    			while(!st.empty()) st.pop();
    			cnt = 0;
    			cnt1 = 0;
    			cnt2 = 0;
    			int len = s.length();
    			for(int i = len - 1;i >= 0;i--){
    				if(s[i]==')'){
    					st.push(s[i]);
    				}
    				else if(s[i]=='*') cnt1++;
    				else{
    					if(!st.empty()) st.pop();
    					else {
    						cnt2++;
    						if(cnt2>cnt1){
    							flag = false;
    							break;
    						}
    					}
    				}
    			}
    			if(!flag) {
    				printf("No solution!\n");
    				continue;
    			}
    			for(int i = len - 1;i>=0&&cnt<cnt2;i--){
    				if(s[i]=='*'){
    					cnt++;
    					s[i] = ')';
    				}
    			}
    			for(int i = 0;s[i];i++){
    				if(s[i]!='*') printf("%c",s[i]);
    			}
    			cout<<endl;
    		}
    	}
    	return 0;
    }
    

      

    第三场一题都补不来OAO,1006太难了

  • 相关阅读:
    Cannot retrieve repository metadata (repomd.xml) for repository: fedora. P、、、
    Fedora 学习总结
    Gnome 高级配置
    [置顶]Fedora 13,14,15安装LAMP
    如何删去Fedora下应用程序菜单中的多余程序启动器?
    运用Telnet在windowsxp中与虚拟机中fedora14互联
    运用Telnet在Windows xp中与虚拟机中fedora14互连
    netstat 的应用
    在 fedora14 下升级 firefox 到 firefox4 的两种方案
    windows 中相关CMD应用
  • 原文地址:https://www.cnblogs.com/ruanbaitql/p/13557271.html
Copyright © 2020-2023  润新知