zoukankan      html  css  js  c++  java
  • 【51Nod 1501】【算法马拉松 19D】石头剪刀布威力加强版

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1501
    dp求出环状不连续的前缀和,剩下东西都可以算出来,比较繁琐。
    时间复杂度(O(n+m))

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    typedef long long ll;
    const int N = 500003;
    
    int a[N], b[N], n, m, f[N][3], id[N];
    ll k, win = 0, los = 0;
    
    int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);}
    
    int main() {
    	scanf("%d%d%lld", &n, &m, &k);
    	for (int i = 0; i < n; ++i)
    		scanf("%d", a + i);
    	for (int i = 0; i < m; ++i)
    		scanf("%d", b + i);
    	int ret = 0;
    	if (n > m) {
    		swap(a, b);
    		swap(n, m);
    		ret ^= 1;
    	}
    	
    	int g = gcd(n, m), delta = n, tmp, tot = 0;
    	for (int i = 0; i < g; ++i)
    		for (int j = 0; j < 3; ++j)
    			f[i][j] = (b[i] == j), id[i] = ++tot;
    	
    	tmp = 0;
    	int tms = m / g;
    	for (int i = 1; i < tms; ++i) {
    		tmp = (tmp + delta) % m;
    		for (int j = tmp; j < tmp + g; id[j] = ++tot, ++j)
    			for (int k = 0; k < 3; ++k)
    				f[j][k] = f[(j - delta + m) % m][k] + (b[j] == k);
    	}
    	
    	int pos, beat, lose, end;
    	for (int i = 0; i < n; ++i) {
    		pos = tmp + i % g;
    		beat = (a[i] + 1) % 3;
    		lose = (a[i] - 1 + 3) % 3;
    		win += f[pos][beat];
    		los += f[pos][lose];
    	}
    	end = tmp;
    	
    	ll lun = 1ll * n * m / g;
    	win = win * (k / lun);
    	los = los * (k / lun);
    	k = k % lun;
    	
    	for (int i = 0; i < n; ++i) {
    		if (i + 1 <= k)
    			tms = (k - i - 1) / n + 1;
    		else
    			continue;
    		pos = i; tmp = (int) ((1ll * delta * (tms - 1) % m + pos) % m);
    		beat = (a[i] + 1) % 3;
    		lose = (a[i] - 1 + 3) % 3;
    		if ((tmp + delta) % m == pos) {
    			win += f[end + i % g][beat];
    			los += f[end + i % g][lose];
    		} else if (pos < g) {
    			win += f[tmp][beat];
    			los += f[tmp][lose];
    		} else
    			if (id[pos] <= id[tmp]) {
    				win += f[tmp][beat] - f[(pos - delta + m) % m][beat];
    				los += f[tmp][lose] - f[(pos - delta + m) % m][lose];
    			} else {
    				win += f[tmp][beat] + f[end + i % g][beat] - f[(pos - delta + m) % m][beat];
    				los += f[tmp][lose] + f[end + i % g][lose] - f[(pos - delta + m) % m][lose];
    			}
    	}
    	
    	if (ret) swap(win, los);
    	printf("%lld %lld
    ", win, los);
    	return 0;
    }
    
  • 相关阅读:
    LeetCode——4Sum
    LeetCode——3Sum
    LeetCode——Longest Repeating Character Replacement
    LeetCode——Longest Palindromic Subsequence
    LeetCode——Longest Word in Dictionary through Deleting
    剑指Offer——丑数
    剑指Offer——最长不包含重复字符的子字符串
    剑指Offer——把数组排成最小的数
    LAMP第四部分mysql操作
    LAMP第三部分php,mysql配置
  • 原文地址:https://www.cnblogs.com/abclzr/p/6040281.html
Copyright © 2011-2022 走看看