• ecjtu-summertraining #10


    A UVA - 10954

    将n个数合并成一个数,每次合并的价值是两个数的和,求最小的总和价值。

    优先队列。

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <algorithm>
     5 #include <queue>
     6 #include <vector>
     7 using namespace std;
     8 #define ll long long
     9 int main(){
    10     ll n,num;
    11     while(scanf("%lld",&n)&&n) {
    12         priority_queue<ll, vector<ll>, greater<ll> >que;
    13         for(int i = 1; i <= n; i ++)cin>>num,que.push(num);
    14         if(que.size()==1){
    15             cout << 0 << endl;
    16             continue;
    17         }
    18         ll sum = 0;
    19         while(que.size() != 1){
    20             ll a = que.top();
    21             que.pop();
    22             ll cnt = que.top();
    23             que.pop();
    24             ll ans = a+cnt;
    25             sum+=ans;
    26             que.push(ans);
    27         }
    28         printf("%lld
    ",sum);
    29     }
    30     return 0;
    31 }

    B - Calendar Game

    Description

    Adam and Eve enter this year's ACM International Collegiate Programming Contest. Last night, they played the Calendar Game, in celebration of this contest. This game consists of the dates from January 1, 1900 to November 4, 2001, the contest day. The game starts by randomly choosing a date from this interval. Then, the players, Adam and Eve, make moves in their turn with Adam moving first: Adam, Eve, Adam, Eve, etc. There is only one rule for moves and it is simple: from a current date, a player in his/her turn can move either to the next calendar date or the same day of the next month. When the next month does not have the same day, the player moves only to the next calendar date. For example, from December 19, 1924, you can move either to December 20, 1924, the next calendar date, or January 19, 1925, the same day of the next month. From January 31 2001, however, you can move only to February 1, 2001, because February 31, 2001 is invalid.

    A player wins the game when he/she exactly reaches the date of November 4, 2001. If a player moves to a date after November 4, 2001, he/she looses the game.

    Write a program that decides whether, given an initial date, Adam, the first mover, has a winning strategy.

    For this game, you need to identify leap years, where February has 29 days. In the Gregorian calendar, leap years occur in years exactly divisible by four. So, 1993, 1994, and 1995 are not leap years, while 1992 and 1996 are leap years. Additionally, the years ending with 00 are leap years only if they are divisible by 400. So, 1700, 1800, 1900, 2100, and 2200 are not leap years, while 1600, 2000, and 2400 are leap years.

    Input

    The input consists of T test cases. The number of test cases (T ) is given in the first line of the input file. Each test case is written in a line and corresponds to an initial date. The three integers in a line, YYYY MM DD, represent the date of the DD-th day of MM-th month in the year of YYYY. Remember that initial dates are randomly chosen from the interval between January 1, 1900 and November 4, 2001.

    Output

    Print exactly one line for each test case. The line should contain the answer "YES" or "NO" to the question of whether Adam has a winning strategy against Eve. Since we have T test cases, your program should output totally T lines of "YES" or "NO".

    Sample Input

    3 
    2001 11 3 
    2001 11 2 
    2001 10 3 

    Sample Output

    YES
    NO
    NO
    博弈论,m+d是偶数就是yes,9月30和11月30要特判下。
     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <algorithm>
     5 #define ll long long
     6 using namespace std;
     7 
     8 int main() {
     9     int t,y,m,d;
    10     scanf("%d",&t);
    11     while(t--) {
    12         scanf("%d%d%d",&y,&m,&d);
    13         if((m+d)%2 ==0 || (m==9&&d==30) || (m==11&&d==30))
    14             puts("YES");
    15         else puts("NO");  
    16     }
    17     return 0;
    18 }

    C - Assemble

    Problem Description
    Recently your team noticed that the computer you use to practice for programming contests is not good enough anymore. Therefore, you decide to buy a new computer.

    To make the ideal computer for your needs, you decide to buy separate components and assemble the computer yourself. You need to buy exactly one of each type of component.

    The problem is which components to buy. As you all know, the quality of a computer is equal to the quality of its weakest component. Therefore, you want to maximize the quality of the component with the lowest quality, while not exceeding your budget.
     
    Input
    On the first line one positive number: the number of testcases, at most 100. After that per testcase:

    One line with two integers: 1 ≤ n ≤ 1 000, the number of available components and 1 ≤ b ≤ 1 000 000 000, your budget.

    n lines in the following format: “type name price quality”, where type is a string with the type of the component, name is a string with the unique name of the component, price is an integer (0 ≤ price ≤ 1 000 000) which represents the price of the component and quality is an integer (0 ≤ quality ≤ 1 000 000 000) which represents the quality of the component (higher is better). The strings contain only letters, digits and underscores and have a maximal length of 20 characters.
     
    Output
    Per testcase:

    One line with one integer: the maximal possible quality.
     
    Sample Input
    1
    18 800
    processor 3500_MHz 66 5
    processor 4200_MHz 103 7
    processor 5000_MHz 156 9
    processor 6000_MHz 219 12
    memory 1_GB 35 3
    memory 2_GB 88 6
    memory 4_GB 170 12
    mainbord all_onboard 52 10
    harddisk 250_GB 54 10
    harddisk 500_FB 99 12
    casing midi 36 10
    monitor 17_inch 157 5
    monitor 19_inch 175 7
    monitor 20_inch 210 9
    monitor 22_inch 293 12
    mouse cordless_optical 18 12
    mouse microsoft 30 9
    keyboard office 4 10
     
    Sample Output
    9
     
    有b元,每种类型的要买一种,每种有个价格和质量,在b元内买的类型中,质量最小的最大化是多少。比赛时想不出怎么贪心,
    赛后看了题解发现是二分+贪心,然后就知道做了,真是不看题解不知道,一看就知道,要多刷题刷题了。
     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <algorithm>
     5 #include <map>
     6 #include <vector>
     7 #define ll long long
     8 using namespace std;
     9 struct Nod{
    10     int c,q;
    11 }t;
    12 map<string,int>mp;
    13 vector<Nod> vs[1010];
    14 int a[1010], T, n, k, b;
    15 bool check(int m) {
    16     ll x = 0;
    17     for(int i = 0; i < k; i ++){
    18         int mins = 0x3f3f3f3f;
    19         for(int j = 0; j < vs[i].size(); j ++) {
    20             if(vs[i][j].q >= m){
    21                 mins = min(mins,vs[i][j].c);
    22             }
    23         }
    24         if(mins == 0x3f3f3f3f)return false;
    25         x += mins;
    26         if(x > b) return false;
    27     }
    28     return x <= b;
    29 }
    30 int main() {
    31     std::ios::sync_with_stdio(false);
    32     scanf("%d",&T);
    33     while(T--) {
    34         mp.clear();
    35         char ss[100], s[100];
    36         string sss;
    37         k = 0;
    38         scanf("%d%d",&n,&b);
    39         for(int i = 0; i <= n; i ++)vs[i].clear();
    40         for(int i = 0; i < n; i ++){
    41             scanf("%s%s%d%d",ss,s,&t.c,&t.q);
    42             sss = ss;a[i] = t.q;
    43             if(!mp.count(sss)){
    44                 mp[sss] = k++;
    45             }
    46             vs[mp[sss]].push_back(t);
    47         }
    48         sort(a,a+n);
    49         int l = 0, r = n-1,ans = 0;
    50         while(l <= r) {
    51             int m = (l+r)>>1;
    52             if(check(a[m])){
    53                 ans = a[m];
    54                 l=m+1;
    55             }
    56             else r = m-1;
    57         }
    58         printf("%d
    ",ans);
    59     }
    60     return 0;
    61 }

    D - Detachment

    将一个数n分成a1+a2+a3....+ak = n的形式,但a1!=a2!=a3...!=ak,求s=a1*a2*a3...*ak的最大值。
     
    关键在于怎么让s最大化,而一段连续的数字可以是值最大化,证明就不说了。让n分为2*3*4*..*k的形式就行。
    不过n是10^9内的数字,不可能全部正好等于2*3*4...的形式,可能会多出△x,而这个△x的值,我可以保证它的范围为0≤△x≤k
    那么有三种情况。
    1、x = k, 比如2*3*4*5 多出一个5 那么可以变成3*4*5*7
    2、x = 0,那就好办了,答案就是k!
    3、0< x < k ,比如3*4*5*6 多出一个3,那么就可以变成3*5*6*7。
    拿第三种情况来说,这个的答案是7!*3!/(2!*4!),这里要对除法进行取摸运算,乘法的到可以直接算,除法的就不行了,要用到乘法逆元。
    直接丢公式:
    满足b*k≡1 (mod MOD)   即b*k%MOD==1%MOD==1的k值就是b关于MOD的乘法逆元。也就是(a/b)%MOD==(a*k)%MOD
     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <algorithm>
     5 #define ll long long
     6 using namespace std;
     7 const int mod = 1e9+7;
     8 const int MAX = 1e5;
     9 ll mul[MAX], add[MAX];
    10 
    11 void exgcd(ll a, ll b, ll &x, ll &y) {
    12     if(!b){
    13         x = 1; y = 0;
    14     }else{
    15         exgcd(b, a%b, y, x);
    16         y -= x*(a/b);
    17     }
    18 }
    19 ll inv(ll a, ll n) {
    20     ll x, y;
    21     exgcd(a, n, x, y);
    22     return (x+n)%n;
    23 }
    24 void init() {
    25     add[0] = add[1] = 0;
    26     add[2] = 2;
    27     mul[0] = mul[1] = 1;
    28     mul[2] = 2;
    29     for(int i = 3; i < MAX; i ++) {
    30         add[i] = add[i-1] + i;
    31         mul[i] = (mul[i-1]*i)%mod;
    32     }
    33 }
    34 int main() {
    35     //std::ios::sync_with_stdio(false);
    36     int t;
    37     ll n;
    38     scanf("%d",&t);
    39     init();
    40     while(t--) {
    41         scanf("%lld",&n);
    42         if(n <= 4){
    43             printf("%lld
    ",n);
    44             continue;
    45         }
    46         int l = 2, r = MAX - 5;
    47         while(l < r) {
    48             int m = (l+r+1) >> 1;
    49             if(add[m] <= n) l = m;
    50             else r = m-1;
    51         }
    52         ll tmp = n-add[l];
    53         if(tmp == l) printf("%lld
    ",mul[l]*inv(2,mod)%mod*(l+2)%mod);
    54         else if(tmp == 0) printf("%lld
    ",mul[l]);
    55         else printf("%lld
    ",mul[l-tmp]*mul[l+1]%mod*inv(mul[l-tmp+1],mod)%mod);
    56     }
    57     return 0;
    58 }

    E - Revenge of Fibonacci

    题目给出斐波那契数列的前k位,k不超过40,找出最小的正整数n,满足F(n)的前k位与给定数的前k位相同,斐波那契数列的项数不超过100000。超过则输出 -1

    这题是最气的,想了好久,在比赛一半是想到了用字典树来做,不过大数加法+字典树却写了我快一个小时,好久不写都生疏了,问题是提交一直错误。

    就只能等赛后看题解了,发现两个问题,1、他的最大值要小于100000,那我非作死的加了一个10,习惯性的加10,让我过不了,还有一个是能用字符数组就用字符数组,坚决不用字符串,输入字符串最大才40个,而我用字符串死活过不去,无意间改成字符数组就过了。。。

    在做的时候 两个加数 只要前40去做加法存在字典树里就行了,不过我让它长度大于100在去截取前面50个,能保证不会出现加法错误。

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <algorithm>
     5 #define ll long long
     6 using namespace std;
     7 const int MAX = 2e5+10;
     8 struct Nod{
     9     Nod* nex[11];
    10     int id;
    11     Nod(){
    12         for(int i = 0; i < 10; i ++)
    13             nex[i] = NULL;
    14             id = -1;
    15     }
    16 }t;
    17 string s,ss;
    18 void mkTrie(string s, int id){
    19     Nod *p = &t;
    20     for(int i = 0; i < s.length(); i ++){
    21         int x = s[i] - '0';
    22         if(p->nex[x] == NULL){
    23             p->nex[x] = new Nod;
    24         }
    25         p = p->nex[x];
    26         if(p->id == -1)
    27             p->id = id;
    28     }
    29 }
    30 int find(char* s){
    31     Nod *p = &t;
    32     for(int i = 0;s[i]; i ++) {
    33         int x = s[i] - '0';
    34         if(p->nex[x] == NULL) return -1;
    35         p = p->nex[x];
    36     }
    37     return p->id;
    38 }
    39 string add(string s, string ss) {
    40     reverse(s.begin(),s.end());
    41     reverse(ss.begin(),ss.end());
    42     int flag = 0;
    43     if(s.length() > ss.length()){
    44         swap(s,ss);
    45     }
    46     int len1 = s.length(), len2 = ss.length();
    47     string sss = "";
    48 //    cout << ss << ' ' << s << endl;
    49     for(int i = 0; i < len2; i ++){
    50         int b = ss[i] - '0', a;
    51         if(i < len1){
    52             a = s[i] - '0';
    53         }else a = 0;
    54         int c = a+b+flag;
    55         if(c > 9){
    56             sss += c-10+'0';
    57             flag = 1;
    58         }else {
    59             sss += c +'0';
    60             flag = 0;
    61         }
    62     }
    63     if(flag) sss += '1';
    64     reverse(sss.begin(),sss.end());
    65     return sss;
    66 }
    67 void init() {
    68     s = "1"; ss = "1";
    69     mkTrie(s,0);mkTrie(ss,1);
    70     for(int i = 2; i < 100000; i ++){
    71         if(s.length() > 100){
    72             reverse(s.begin(),s.end());
    73             reverse(ss.begin(),ss.end());
    74             s = s.substr(50,1000);
    75             ss = ss.substr(50,1000);
    76             reverse(s.begin(),s.end());
    77             reverse(ss.begin(),ss.end());
    78         }
    79         string sss = add(s,ss);
    80         mkTrie(sss,i);
    81         s = ss;
    82         ss = sss;
    83     }
    84 }
    85 
    86 int main() {
    87     //std::ios::sync_with_stdio(false);
    88     init();
    89     int t;
    90     scanf("%d",&t);
    91     for(int i = 1; i <= t; i ++) {
    92         char s[60];//这里一定要用字符数组,用string就会答案错误。不知道怎么一回事。
    93         scanf("%s",s);
    94         printf("Case #%d: %d
    ",i,find(s));
    95     }
    96     return 0;
    97 }
  • 相关阅读:
    广播的最佳实践---实现强制下线功能
    广播的最佳实践---实现强制下线功能
    使用本地广播
    使用本地广播
    关于Win7固态优盘的优化方法
    关于Win7固态优盘的优化方法
    在屏幕中使用评分组件
    在屏幕中使用评分组件
    【NYOJ】[65]另一种阶乘问题
    【NYOJ】[65]另一种阶乘问题
  • 原文地址:https://www.cnblogs.com/xingkongyihao/p/7246865.html
Copyright © 2020-2023  润新知