菜是原罪der惹某第13周周记(习题+感悟)

(一)2019 ICPC Asia Xuzhou Regional

A - < 3 numbers

题目描述

    Rosie likes to play with positive integers, especially the < 3 numbers in positive integers.
    < 3 number is a special group of positive integers, all of which can be divided by less than three positive integers.
    For example, 7 is a < 3 number. There are two positive integers that divide 7 by 1 and 7. 25 is not a number less than 3. There are 1, 5 and 25 that can divide 25.
    Now, Rosie is curious about how many < 3 numbers are included between positive integers L and R. But it’s too difficult to figure out exactly how many < 3 numbers there are. Rosie wants to know whether the proportion of < 3 numbers between L and R is less than one third. To be exact, if there are x < 3 numbers between L and R, Rosie wants to know if x / (R−L+1) < 1/3 .
    Please help the curious Rosie to answer his questions.

Input

    The first line has a positive integer of T, which represents the total number of test data.
    Each test data is a line of two integers L, R.
    · 1 ≤ T ≤ 100
    · 1 ≤ L ≤ R ≤ 1e9

Output

    Please output one line for each test data. If the proportion of < 3 numbers between L and R is less than one third, output Yes, otherwise output No.

Sample Input

3
7 7
25 25
5 14

Sample Output

No
Yes
No

理解

这题原本上手的时候卡了一下,然后李妍薇大佬说素数的分布是越来越稀疏的
然后暴力打表打了几个找了一下规律
然后这题有需要注意的是1也是满足条件的
然后可以发现左右区间大小大于50的时候一定是 < 1/3 的,所以直接输出Yes
当区间小于50 的时候,暴力跑一遍不会超时,直接判断就完事了

AC代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 100010;
int prime[maxn + 10];

bool is_prime(int x){
    if(x == 1)  return true;
    for(int i = 2; i * i <= x; i++){
        if(x % i == 0)
            return false;
    }
    return true;
}
int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        int l, r;
        scanf("%d %d", &l, &r);
        if(r - l + 1 >= 50){
            printf("Yes\n");
        }else{
            int ans = 0;
            for(int i = l; i <= r; i++){
                if(is_prime(i)){
                    ans++;
                }
            }
            if(r - l + 1 > ans * 3){
                printf("Yes\n");
            }else{
                printf("No\n");
            }
        }
    }
    return 0;
}

B - Cat

题目描述

    Yen-Jen loves cat very much.
    Now, there are 1e18 cats standing in a line, the i-th cat’s cost value ci is equal to i, the i-th cat’s index is also equal to i.
    Now, Yen-Jen wants to buy some cats with continuous index, but he only has S dollars. He wants to buy some cats with continuous indices. In order to buy cat with index x, x + 1,…, y - 1, y, he needs to spend x⊕(x+1)⊕⋯⊕(y−1)⊕y dollars. ⊕ is the bitwise exclusive-or operator.
    Now, he wants to ask you T questions. In each question, he has S dollars, and he wants the indices of cats in range [L, R]. What’s the maximum number of cat that Yen-Jen can buy? If he can’t buy any cat, please report -1 instead.

Input

    The first line of the input file contains one integer T denotes the number of questions that Yen-Jen wants to challenge you.
    Then, in the next T lines, each line contains one question. In each line, there are three integers L, R, S, which means that Yen-Jen has S dollars, and he wants to buy cats whose indices are in the range [L, R].
    ·1 ≤ T ≤ 5×1e5
    ·1 ≤ L ≤ R ≤ 1e18
    ·0 ≤ S ≤ 2×1e18

Output

    In each question, output the maximum number of cats that Yen-Jen can buy. If Yen-Jen can’t buy any cats, output -1 instead.

Sample Input

2
1 1 0
2 2 2

Sample Output

-1
1

理解

起先根据异或自己试了 0^1 1^2 3^4 几组 然后发现 2^3^4^5 == 0 然后错以为 四个相连都是为 0
然后发现只有结尾是奇数才能实现 四个连续的数字异或为 0 
那么就可以简单地处理一下 这一串连续的数字
因为题目要求连续的取 所以先判断一下最后一个是奇数还是偶数 
如果是奇数就往前4个4个的取,肯定异或完都是0,
然后在判断前面剩下的最多能取几个就好了
如果是偶数 就先不取最后一个 然后从倒数第二个开始往前4个4个取都异或为 0 
然后剩下 < 4 的个数直接暴力判断 
WA了很多发,怪我代码码的太乱了,后来还是找错误样例才发现了很多漏洞
这个码字能力是我太弱了(嘤嘤嘤)

AC代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
int main()
{
    int cas;
    scanf("%d",&cas);
    while(cas--){
    	ll l,r,s;
    	scanf("%lld %lld %lld",&l,&r,&s);
    	ll m = (r - l + 1) % 4;
    	ll sum = (r - l + 1) / 4 * 4;
    	if(sum == 0){
    		if(m == 3){
	    		if((l^(l+1)^(l+2)) <= s) printf("3\n");
				else if((l^(l+1)) <= s) printf("2\n");
				else if(((l+1)^(l+2)) <= s) printf("2\n");
				else if(s >= l) printf("1\n");
				else printf("-1\n");
			}
			else if(m == 2){
				if((l^(l+1)) <= s) printf("2\n");
				else if(s >= l) printf("1\n");
				else printf("-1\n");
			}
			else if(m == 1){
				ll t = l;
				if(t <= s) printf("1\n");
				else printf("-1\n");
			} 
			continue;
		}
		else if(sum == 4 && m == 0){
			if(r % 2)	printf("4\n");
			else{
				ll k;
				if((l^(l+1)^(l+2)^(l+3)) <= s) printf("4\n");
				else if((l^(l+1)^(l+2)) <= s) printf("3\n");
				else if( ((l+1)^(l+2)^(l+3)) <= s) printf("3\n");
				else if((l^(l+1)) <= s) printf("2\n");
				else if(((l+1)^(l+2)) <= s) printf("2\n");
				else if(((l+2)^(l+3)) <= s) printf("2\n");
				else if(s >= l) printf("1\n");
				else printf("-1\n");
			}
			continue;
		}
		if(r % 2 == 1){
			if(m == 3){
	    		if((l^(l+1)^(l+2)) <= s) printf("%lld\n",sum+3);
				else if(((l+1)^(l+2)) <= s) printf("%lld\n",sum+2);
				else if(s >= l+2) printf("%lld\n",sum+1);
				else printf("%lld\n",sum);
			}
			else if(m == 2){
				if((l^(l+1)) <= s) printf("%lld\n",sum+2);
				else if(s >= l+1) printf("%lld\n",sum+1);
				else printf("%lld\n",sum);
			}
			else if(m == 1){
				ll t = l;
				if(t <= s) printf("%lld\n",sum+1);
				else printf("%lld\n",sum);
			} 
			else if(m == 0) printf("%lld\n",sum);
		}
    	else{
    		if(m == 3){
	    		if((l^(l+1)^r) <= s) printf("%lld\n",sum+3);
				else if((l^(l+1)) <= s) printf("%lld\n",sum+2);
				else if(((l+1)^r) <= s) printf("%lld\n",sum+2);
				else if(s >= l+1) printf("%lld\n",sum+1);
				else printf("%lld\n",sum);
			}
			else if(m == 2){
				if((l^r) <= s) printf("%lld\n",sum+2);
				else if(s >= l) printf("%lld\n",sum+1);
				else printf("%lld\n",sum);
			}
			else if(m == 1){
				ll t = r;
				if(t <= s) printf("%lld\n",sum+1);
				else printf("%lld\n",sum);
			} 
			else if(m == 0){
				sum-=4;
				if((l^(l+1)^(l+2)^r) <= s) printf("%lld\n",sum+4);
				else if((l^(l+1)^(l+2)) <= s) printf("%lld\n",sum+3);
				else if( ((l+1)^(l+2)^r) <= s) printf("%lld\n",sum+3);
				else if(((l+1)^(l+2)) <= s) printf("%lld\n",sum+2);
				else if(((l+2)^r) <= s) printf("%lld\n",sum+2);
				else if(s >= l+2) printf("%lld\n",sum+1);
				else printf("%lld\n",sum);
			}
		}
	}
    return 0;
}

C - The Answer to the Ultimate Question of Life, The Universe, and Everything.

题目描述

    For decades, scientists have wondered whether each of the numbers from 0 to 100 could be represented as the sum of three cubes, where a cube is the same number multiplied together three times.
    42 was the last number without a proven solution — until now.
    The solution is (-80538738812075974)^3 + (80435758145817515)^3 + (12602123297335631)^3 = 42
    Now, Yen-Jen is suspicious of the existence of other solutions. But, the solutions are not so trivial to find out. Yen-Jen wants to find out easysolutions first. That is, for the equation a^3 + b^3 + c^3 = x,Yen-Jen wants to find out at least one solution for each integer x in [0, 200],where ∣a∣,∣b∣,∣c∣≤5000.
    Since Yen-Jen is still busy preparing the test data of some(this?) problem, pleasehelp him find out at least one solution for each xx or tell him that thesolution doesn’t exist when∣a∣,∣b∣,∣c∣≤5000.

Input

    The first line contains an integer T indicating the number of x to bechecked.Following T lines each contains one integer x.
    ·1 ≤ T ≤ 10
    ·0 ≤ x ≤ 200

Output

    For each test case, output one line containing three space-separated integers a, b, ca,b,c such that a^3 + b^3 + c^3 = x and ∣a∣,∣b∣,∣c∣≤5000. If thesolution doesn’t exist, output impossible.

Sample Input

2
1
2

Sample Output

1 1 -1
1 1 0

理解

这道题,其实我理解了题意后并没有什么想法
优秀的张李彬同学和他的小伙伴们,暴力打表了(足够优秀昂)

AC代码

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = 210;
struct node{
    int x, y, z;
}a[maxn];
int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        int n;
        scanf("%d", &n);
		if(n == 0) printf("5000 0 -5000\n");
		else if(n == 1) printf("5000 1 -5000\n");
		else if(n == 2) printf("4375 -486 -4373\n");
		else if(n == 3) printf("4 4 -5\n");
		else if(n == 6) printf("236 -55 -235\n");
		else if(n == 7) printf("168 44 -169\n");
		else if(n == 8) printf("5000 2 -5000\n");
		else if(n == 9) printf("217 -52 -216\n");
		else if(n == 10) printf("683 -353 -650\n");
		else if(n == 11) printf("297 619 -641\n");
		else if(n == 12) printf("7 10 -11\n");
		else if(n == 15) printf("332 -262 -265\n");
		else if(n == 16) printf("2594 -432 -2590\n");
		else if(n == 17) printf("2195 2977 -3331\n");
		else if(n == 18) printf("1671 -1276 -1373\n");
		else if(n == 19) printf("47 91 -95\n");
		else if(n == 20) printf("2833 -741 -2816\n");
		else if(n == 21) printf("445 -287 -401\n");
		else if(n == 24) printf("8 8 -10\n");
		else if(n == 25) printf("2357 1839 -2683\n");
		else if(n == 26) printf("2106 237 -2107\n");
		else if(n == 27) printf("3 5000 -5000\n");
		else if(n == 28) printf("1541 -473 -1526\n");
		else if(n == 29) printf("235 -233 -69\n");
		else if(n == 34) printf("1557 -244 -1555\n");
		else if(n == 35) printf("1154 -509 -1120\n");
		else if(n == 36) printf("2731 2358 -3223\n");
		else if(n == 37) printf("445 -444 -84\n");
		else if(n == 38) printf("25 16 -27\n");
		else if(n == 43) printf("837 -307 -823\n");
		else if(n == 44) printf("8 -7 -5\n");
		else if(n == 45) printf("2025 1709 -2369\n");
		else if(n == 46) printf("815 -473 -758\n");
		else if(n == 47) printf("139 49 -141\n");
		else if(n == 48) printf("3991 -1247 -3950\n");
		else if(n == 51) printf("602 659 -796\n");
		else if(n == 53) printf("2141 1518 -2370\n");
		else if(n == 54) printf("3891 -648 -3885\n");
		else if(n == 55) printf("1837 3131 -3329\n");
		else if(n == 56) printf("505 559 -672\n");
		else if(n == 57) printf("361 982 -998\n");
		else if(n == 60) printf("1202 -163 -1201\n");
		else if(n == 61) printf("668 845 -966\n");
		else if(n == 62) printf("2903 -1561 -2744\n");
		else if(n == 63) printf("102 146 -161\n");
		else if(n == 64) printf("5000 4 -5000\n");
		else if(n == 65) printf("403 903 -929\n");
		else if(n == 66) printf("4 1 1\n");
		else if(n == 69) printf("398 134 -403\n");
		else if(n == 70) printf("824 2325 -2359\n");
		else if(n == 71) printf("443 401 -533\n");
		else if(n == 72) printf("434 -104 -432\n");
		else if(n == 73) printf("344 -146 -335\n");
		else if(n == 78) printf("2123 -2080 -829\n");
		else if(n == 79) printf("711 -706 -196\n");
		else if(n == 80) printf("1366 -706 -1300\n");
		else if(n == 81) printf("2638 -2368 -1719\n");
		else if(n == 82) printf("1188 847 -1317\n");
		else if(n == 83) printf("3651 1315 -3707\n");
		else if(n == 87) printf("4271 -1972 -4126\n");
		else if(n == 88) printf("1686 -1282 -1390\n");
		else if(n == 89) printf("2036 1953 -2514\n");
		else if(n == 90) printf("365 1798 -1803\n");
		else if(n == 91) printf("364 1332 -1341\n");
		else if(n == 92) printf("861 4039 -4052\n");
		else if(n == 93) printf("253 -248 -98\n");
		else if(n == 96) printf("14 20 -22\n");
		else if(n == 97) printf("3200 -991 -3168\n");
		else if(n == 98) printf("2391 -1638 -2101\n");
		else if(n == 99) printf("259 756 -766\n");
		else if(n == 100) printf("1870 -903 -1797\n");
		else if(n == 101) printf("319 2325 -2327\n");
		else if(n == 102) printf("118 229 -239\n");
		else if(n == 105) printf("8 -4 -7\n");
		else if(n == 106) printf("2760 -2689 -1165\n");
		else if(n == 107) printf("1117 947 -1309\n");
		else if(n == 108) printf("1345 -948 -1165\n");
		else if(n == 109) printf("853 2924 -2948\n");
		else if(n == 111) printf("4966 -4793 -2312\n");
		else if(n == 115) printf("11 8 -12\n");
		else if(n == 116) printf("1945 -757 -1906\n");
		else if(n == 117) printf("962 -555 -896\n");
		else if(n == 118) printf("383 4327 -4328\n");
		else if(n == 119) printf("2326 -609 -2312\n");
		else if(n == 120) printf("2725 1219 -2804\n");
		else if(n == 123) printf("38 -37 -16\n");
		else if(n == 124) printf("5 0 -1\n");
		else if(n == 125) printf("5000 5 -5000\n");
		else if(n == 126) printf("2217 -2212 -419\n");
		else if(n == 127) printf("4988 -3881 -4034\n");
		else if(n == 128) printf("3997 -726 -3989\n");
		else if(n == 129) printf("1801 -1238 -1580\n");
		else if(n == 132) printf("5 2 -1\n");
		else if(n == 133) printf("389 167 -399\n");
		else if(n == 134) printf("3203 -3013 -1766\n");
		else if(n == 135) printf("1395 -629 -1351\n");
		else if(n == 136) printf("816 946 -1116\n");
		else if(n == 137) printf("801 -428 -758\n");
		else if(n == 138) printf("103 -77 -86\n");
		else if(n == 141) printf("116 104 -139\n");
		else if(n == 142) printf("8 -7 -3\n");
		else if(n == 144) printf("3342 -2552 -2746\n");
		else if(n == 145) printf("10 -7 -8\n");
		else if(n == 146) printf("376 -263 -327\n");
		else if(n == 147) printf("1528 2131 -2366\n");
		else if(n == 150) printf("260 317 -367\n");
		else if(n == 151) printf("447 215 -463\n");
		else if(n == 152) printf("486 741 -805\n");
		else if(n == 153) printf("1083 -365 -1069\n");
		else if(n == 154) printf("1077 1717 -1848\n");
		else if(n == 155) printf("3721 -1049 -3693\n");
		else if(n == 159) printf("1526 383 -1534\n");
		else if(n == 160) printf("3972 -1654 -3874\n");
		else if(n == 161) printf("4980 -2476 -4767\n");
		else if(n == 162) printf("4180 -1417 -4125\n");
		else if(n == 163) printf("4033 -2943 -3423\n");
		else if(n == 164) printf("79 -59 -66\n");
		else if(n == 168) printf("890 -574 -802\n");
		else if(n == 169) printf("1521 -1012 -1354\n");
		else if(n == 170) printf("4047 -3834 -2149\n");
		else if(n == 171) printf("891 1178 -1328\n");
		else if(n == 174) printf("349 -170 -335\n");
		else if(n == 177) printf("1169 -160 -1168\n");
		else if(n == 178) printf("15 -10 -13\n");
		else if(n == 179) printf("1503 2691 -2839\n");
		else if(n == 181) printf("4861 974 -4874\n");
		else if(n == 182) printf("91 -29 -90\n");
		else if(n == 183) printf("976 4876 -4889\n");
		else if(n == 186) printf("5 5 -4\n");
		else if(n == 187) printf("2000 -1092 -1885\n");
		else if(n == 188) printf("318 1635 -1639\n");
		else if(n == 189) printf("1974 -1702 -1403\n");
		else if(n == 190) printf("4815 -593 -4812\n");
		else if(n == 191) printf("399 -215 -377\n");
		else if(n == 192) printf("4 4 4\n");
		else if(n == 196) printf("8 3 -7\n");
		else if(n == 197) printf("3026 -1606 -2867\n");
		else if(n == 198) printf("3809 -1347 -3752\n");
		else if(n == 199) printf("508 2199 -2208\n");
		else if(n == 200) printf("103 73 -114\n");
		else printf("impossible\n");
    }
    return 0;
}

(二)2019 ICPC Asia Nanchang Regional

A - And and Pair

题目描述

    Given an extremely large non-negative integer nn, you are asked to count the number of pairs (i,j) of integers satisfying the following conditions:
    0 ≤ j ≤ i ≤ n;
    i & n = i; and
    i & j = 0.
    Here & represents the bitwise AND operator.
    For simplicity, the binary representation of n will be given. Meanwhile, you only need to output the answer modulo (10^9+7).

Input

    The first line contains an integer T (1 ≤ T ≤ 20) indicating the number of test cases.
    Each of the following T lines contains a string S (1 ≤ ∣S∣ ≤ 1e5) which is the binary representation of the non-negative integer nn. Note that leading zeros of S could appear in the input.

Output

    For each test case, output a line containing the answer described above modulo (10^9+7).

Sample Input

2
111
1010

Sample Output

14
15

理解

起先卡在了找规律上,三个人埋头苦想了一年的规律
果然还是先暴力打一遍找规律昂
然后最先发现的是,通过 i 去推 j 的时候,只要看 每个 i 最高 1 位后有几个 0 就有2的几次方个 j
然后 i 的规律 是看 n 的二进制里 每位的 0 必定对应 0,而 1 位可以对应0/1 但是不同的 i 和 j 对应就毫无头绪
然后我和张李彬去开了 L题,优秀的思维大佬(李妍薇)在静想了一会后 发现了总个数的规律
是看每一位后面的1和0的个数来相加的,每次* (2 的 num0次 + 3 的 num1 次) 
然后值得注意的是当数量为 0 的时候不在计入
所以只需要跑一遍字符串记录0 1 个数
然后从头往后推 每次 遇到 1 就 * 一遍上面的公式 ,然后 num1-- ,遇到 0 就num0--;
wa了一发小细节(嘤嘤嘤)

AC代码

#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
ll poww(ll a, ll b){
    ll ans = 1, base = a;
    while(b != 0){
        if(b & 1 != 0)
            ans = base * ans % mod;
        base = base * base % mod;
        b >>= 1;
    }
    return ans;
}
int main(){
    int cas;
    scanf("%d",&cas);
    while(cas--){
    	string s;
    	cin >> s;
    	int num1 = 0,num0 = 0;
    	for(int i = 0;i < s.length();i++){
    		if(s[i] == '1') num1++;
    		if(s[i] == '0') num0++;
		}
//		cout << num0 <<" " << num1 << endl;
		ll ans = 0;
		for(int i = 0;i < s.length();i++){
			if(s[i] == '1' && i == s.length()-1){
				ans += 2;
				break;
			}
			if(s[i] == '0' && i == s.length()-1){
				ans += 1;
				break;
			}
    		if(s[i] == '1'){
    			num1--;
    			ll cnt = 1;
    			if(num0 != 0) cnt *= poww(2,num0) ;
    			cnt %= mod;
    			if(num1 != 0) cnt *= poww(3,num1);
    			cnt %= mod;
    			ans += cnt;
    			ans %= mod;
			}
    		else if(s[i] == '0') num0--;
//    		cout << "ans = " << ans << endl;
		}
		printf("%lld\n",ans % mod);
	}
    return 0;
}

B - Who is the Champion

题目描述

    Soccer is probably the sport with the greatest fans in this country. However, the national team has a poor record on the world stage. In order to energize youth players, the Soccer National Championship is organized every year.
    In this year, there are nn teams taking part in the championship. As usual, the single round-robin system is adopted so that each team plays every other team once. A standard match askes ten players and a goalkeeper for both teams, which contains 22 players in total. They confront each other, defend their nets and attack the opponent’s goal in a rectangular grass court.
    In a 90-minute game, they try to shoot again and again. When the game is over, the team with higher goals will win and obtain 3 points in the scoreboard, while the loser will obtain nothing. A very special but common case is that both teams get the same goals, which is a draw; then both of them will obtain one point in the scoreboard.
    At the end of the season, the league will declare the champion which is the team with the highest score in total. If two or more teams have the same highest score in total, the one with the highest goal differential (which is calculated as the number of goals scored in all league matches minus the number of goals conceded) will be the champion. The worst situation that several teams have the same highest score in total and the same goal differential will be solved by extra play-offs.

Input

    The first line contains an integer n (1 ≤ n ≤ 100) indicating the number of teams.
    Each of the following nn lines contains nn integers.The j-th integer in the i-th line, which is non-negative and up to five, represents the number of goals scored by the i-th team against the j-th team.
    We guarantee that a(i,i)=0 for all 1 ≤ i ≤ n.

Output

    If the league can declare the champion, output the index of the team who will be the champion or output play-offs (without quotes), if extra play-offs will be organized.

Sample Input

样例输入1
2
0 1
2 0
样例输入2
2
0 1
1 0
样例输入3
3
0 1 3
1 0 4
0 0 0

Sample Output

样例输出1
2
样例输出2
play-offs
样例输出3
2

理解

这题讲了一堆废话,就是平局两者各记+1分,不是平局就赢家+3分
然后如果出现总分一样就记录这些球队总的进球数和输球数
然后只需要在输入后开三个数组,一个记录总分,一个记录进球总数,一个输球总数
起先wa一发是。。。莫名其妙自己sort了一下,,,是我太傻了
就是一道暴力题,小问题

AC代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int mp[105][105];
int book[106];int com[105];
int main(){
    int n;
    scanf("%d",&n);
    memset(mp,0,sizeof(mp));
    for(int i = 1;i <= n;i++){
    	for(int j = 1;j <= n;j++){
    		scanf("%d",&mp[i][j]);
		}
	}
	int zf[105],ball[105],lose[105];
	memset(zf,0,sizeof(zf));
	memset(ball,0,sizeof(ball));
	memset(lose,0,sizeof(lose));
	for(int i = 1;i <= n;i++){
    	for(int j = 1;j <= n;j++){
    		if(i == j || book[j]) continue;
    		if(mp[i][j] == mp[j][i]){
    			zf[i] += 1;
    			zf[j] += 1;
			}
			else if(mp[i][j] > mp[j][i]){
    			zf[i] += 3;
			}
			else if(mp[i][j] < mp[j][i]){
    			zf[j] += 3;
			}
		}
        book[i] = 1;
	}
	for(int i = 1;i <= n;i++){
    	for(int j = 1;j <= n;j++){
    		ball[i] += mp[i][j];
    		lose[i] += mp[j][i];
		}
	}
	int maxn = -0x3f3f3f,idx = 0;
	for(int i = n;i >= 1;i--){
		if(zf[i] > maxn){
            idx = 0;
			maxn = zf[i];
			com[idx++] = i;
		}else if(zf[i] == maxn){
            com[idx++] = i;
        }
	}
	if(idx == 1) printf("%d\n",com[0]);
	else{
		int maxx = -0x3f3f3f;
		int id = -1;
		for(int i = 0;i < idx;i++){
			if(ball[com[i]] - lose[com[i]]> maxx){
				maxx = ball[com[i]] - lose[com[i]];
				id = com[i];
			}
		}
		int cnt = 0; 
		for(int i = 0;i < idx;i++){
			if(ball[com[i]] - lose[com[i]] == maxx) cnt++;
			if(cnt >= 2) break;
		} 
		if(cnt >= 2) printf("play-offs\n");
		else printf("%d\n",id);
	}
	
    return 0;
}

C - Bob’s Problem

题目描述

    Bob was in trouble.He rubbed the magic ring on his finger, and you came out of the ground.
    You are given an undirected graph G which contains nn vertices labelled from 1 to n, with mm weighted edges between them coloured in black or white.You have to choose some edges in G such that there is at least one path between any two vertices only passing by selected edges, and you can select no more than k white edges.There may be multiple available strategies to determine these edges, and you are asked to find out the way with a maximum total weight of edges.

Input

    The first line contains an integer T (1 ≤ T ≤ 5) indicating the number of test cases.
    For each test case, the first line contains three integers n (1 ≤ n ≤ 50000), m and k (1 ≤ k ≤ m ≤ 500000).
    Each of the following mm lines contains four integers u, v (1 ≤ u,v ≤ n),w (0 ≤ w ≤ 100000) and c (0 ≤ c ≤ 1) describing an edge of weight ww and colour cc between the u-th vertex and the v-th vertex. Here an edge is white if c = 1, or black if c = 0.
    Note that there may be multiple edges between some vertices, and self-loops are also allowed.

Output

    For each test case, output a single line with an integer indicating the maximum total weight of selected edges, or output -1 if there is no solution for the given graph.

Sample Input

1
5 6 2
1 2 0 0
1 3 5 1
1 5 1 0
2 3 6 1
2 4 2 0
3 4 7 1

Sample Output

16

理解

再夸一波图论小能手张李彬同学
首先看完题意推了一波 发现只限制了白边条数
所以黑边是一定会加上的
然后要求连通每个点
此时再去对白边的增加做判断即可
wa两发的原因是没开 long long 嘤嘤嘤

AC代码

#include<iostream>
#include<algorithm>
#include<queue>
#include<string.h>
using namespace std;
typedef long long ll;
const int maxn = 50010;
const int maxm = 500010;
int book[maxm];
int f[maxn];
struct node{
    int u, v, w;
}edge[maxm], edge2[maxm];
int tol, n, m, k, tol2;
bool cmp(node a, node b){
    return a.w > b.w;
}

int find(int x){
    if(f[x] == -1)  return x;
    else    return f[x] = find(f[x]);
}

void init(){
    memset(f, -1, sizeof(f));
    memset(book, 0, sizeof(book));
    tol = tol2 = 0;
}
int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        init();
        scanf("%d %d %d", &n, &m, &k);
        for(int i = 1; i <= m; i++){
            int u, v, val, c;
            scanf("%d %d %d %d", &u, &v, &val, &c);
            if(c == 0){
                edge[tol].u = u;edge[tol].v = v;edge[tol++].w = val;
            }else{
                edge2[tol2].u = u;edge2[tol2].v = v;edge2[tol2++].w = val;
            }
        }
        ll cnt = 0, ans = 0, num = 0;
        for(int i = 0; i < tol; i++){
            int u = edge[i].u, v = edge[i].v, w = edge[i].w;
            int t1 = find(u);
            int t2 = find(v);
            if(t1 != t2){
                ans += w;
                f[t1] = t2;
                cnt++;
            }else{
                ans += w;
            }
        }
        sort(edge2, edge2 + tol2, cmp);
        for(int i = 0; i < tol2; i++){
            int u = edge2[i].u, v = edge2[i].v, w = edge2[i].w;
            int t1 = find(u);
            int t2 = find(v);
            if(t1 != t2){
                ans += w;
                cnt++;
                f[t1] = t2;
                num++;
                book[i] = 1;
            }
            if(num >= k)    break;
        }
        if(cnt != n - 1)    printf("%d\n", -1);
        else{
            if(num < k){
                for(int i = 0; i < tol2; i++){
                    if(book[i] == 0){
                        num++;
                        ans += edge2[i].w;
                    }
                    if(num >= k)    break;
                }
            }
            printf("%lld\n", ans);
        }
    }
    return 0;
}

D - Eating Plan

题目描述

    Bob is hungry now and he needs to eat some food. Alice puts nn dishes of food in front of him, numbered from 1 to n. Alice tells him that he can only eat continuous dishes of food, or he will be poisoned by food. For example, if there are 10 dishes, he can eat the food in the 2-nd, 3-rd and 4-th dishes but he can not eat the food in the 2-nd, 3-rd and 5-th dishes because there is the 4-th dish between them so it’s not continuous. Furthermore, if he chooses to eat food in the ii-th dish, he has to eat all food in that dish.
    Bob’s stomach has a strange feature that if there is at least t (=998857459) kg food in it, the weight in it will reduce t kg repeatedly until it is strictly lower than tt kg. Also, if the weight of food in his stomach is exactly t kg, his stomach will be empty. Now Bob wants to eat the smallest number of dishes and remains no less than k kg food in his stomach. Can you tell him how many dishes he needs to choose?

Input

    The first line contains two integers nn and m~(1\leq n\leq 100000,1\leq m\leq 10000)m (1 ≤ n ≤ 100000,1 ≤ m ≤ 10000), indicates the number of dishes and the number of queries.
    The second line contains n integers a1,a2,⋯,an, which is a permutation of 1,2,⋯,n, indicates that there is (ai!) kg food in the ii-th dish, where s! = 1×2×3×⋯×s.
    The third line contains mm integers, the i-th integer ki(1 ≤ ki < t) indicates a query with the lower bound of weight.

Output

    Each line of mm lines contains an integer indicates the number of dishes Bob needs to choose in that query. If there is no way to reach Bob’s target, output -1 instead.

Sample Input

4 2
1 2 3 4
29 31

Sample Output

2
3

理解

在此一定要吹一波紫妈(某陈姓大佬)最后几分钟A了,也太强了
代码不是我码的,后来还找他帮我分析了一波题目思路(我吹爆)
首先根据题意 暴力打表 数字的阶乘 然后对 t 取模 找了一波规律 然后发现 到2802

在这里插入图片描述

	刚好 % 2803 == 0 然后后面都是 0 了
	然后只需要打表打到3000(保险起见)
	然后记录输入的每个点的下标和值
	然后用一个n^2的循环来枚举每一个区间,记录下每一个区间的下标和长度,以及大小
	然后进行一次排序 先根据 值从小到大 然后根据长度从小到大
	然后暴力循环 直到找到第一个区间 的值比询问的k大
	从这个区间往后都是满足条件的
	然后用一个线段树 维护一个最小区间
	就可以得到答案啦!

AC代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll; 
const int maxN = 3e3+10;
const int N = 9e6+10;
const ll M = 998857459;
struct point{
	int idx;
	ll v;
	point(){}
	point(ll v,ll idx):v(v),idx(idx){}
} p[maxN];
struct node{
	int len,v;
	node(){}
	node(ll v,ll len):v(v),len(len){}
} k[N];
int tot,cnt;
ll f[maxN];
int Min[N << 2];

void pushup(int rt){
	Min[rt] = min(Min[rt << 1],Min[rt << 1|1]);
	return ;
}

void build(int rt,int l,int r){
	if(l == r){
		Min[rt] = k[l].len;
		return ;
	}
	int m = (l+r)>>1;
	build(rt << 1,l,m);
	build(rt << 1|1,m+1,r);
	pushup(rt);
	return ;
}

inline int query(int rt,int l,int r,int L,int R){
	if(L <= l && r <= R) return Min[rt];
	int m = (l+r) >> 1;
	int ans = 0x3f3f3f3f;
	if(L <= m) ans = min(ans,query(rt << 1,l,m,L,R));
	if(R > m) ans = min(ans,query(rt << 1|1,m+1,r,L,R));
	return ans;
}

void f_table(){
	f[1] = 1;
	for(ll i = 2;i <= 3000;++i) f[i] = (f[i-1]*i)%M;
	return ;
}

bool cmp(node a,node b){
	if(a.v == b.v) return a.len < b.len;
	return a.v < b.v;
}

int main()
{
	f_table();
	int n,m,x;
	scanf("%d%d",&n,&m);
	cnt = tot = 0;
	
	for(int i = 1;i <= n;++i){
		scanf("%d",&x);
		if(x <= 3000 && f[x]) p[++tot] = point(f[x],i);
	}
	
	for(int i = 1;i <= tot;++i){
		ll sum = 0;
		for(int j = i;j <= tot;++j){
			sum = (sum+p[j].v)%M;
			k[cnt++] = node(sum,p[j].idx-p[i].idx+1);
		}
	}
	sort(k,k+cnt,cmp);
	build(1,0,cnt-1);
	
	ll o;
	for(int i = 1;i <= m;++i){
		scanf("%lld",&o);
		ll l = 0,r = cnt-1,mid,half;
		while(r > 0){
			half = r >> 1;
			mid = l+half;
			if(k[mid].v >= o) r = half;
			else{
				l = mid+1;
				r = r-half-1;
			}
		}
		
		if(k[l].v < o) printf("-1\n");
		else printf("%d\n",query(1,0,cnt-1,l,cnt-1));
	}
	return 0;
}

(三)我的感想(略略略)

关于这周的日常练习

这两次的徐州和南昌重现赛感觉配合略好些了,一个人思考的时候,另外两个人开新题,
毕竟有很多签到题(误)然后就分工合作
真的很躺赢,毕竟有一个思维大佬和一个图论大佬带我,嘤嘤嘤
这周的dp专题也没有好好的刷起来,刷题速度太慢了,,,
然后感觉离西安的时间越来越近了,一边紧张一边划水(误)应该是一边学习!
不会的东西好多 学不完啦,不过没关系,学到就是赚到 over
以及今天写博客的时候发现一个很骚的操作
如下:如何在CSDN上搞花里胡哨的爱心(嘻嘻)

❤️ ❤️ ❤️ ❤️ ❤️ ❤️

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值