C++——USACO Section 2.2 题解

44 篇文章 0 订阅

Preface Numbering

A certain book's prefaces are numbered in upper case Roman numerals. Traditional Roman numeral values use a single letter to represent a certain subset of decimal numbers. Here is the standard set:

        I   1     L   50    M  1000
        V   5     C  100
        X  10     D  500

As many as three of the same marks that represent 10n may be placed consecutively to form other numbers:

  • III is 3
  • CCC is 300

Marks that have the value 5x10n are never used consecutively.

Generally (with the exception of the next rule), marks are connected together and written in descending order to form even more numbers:

  • CCLXVIII = 100+100+50+10+5+1+1+1 = 268

    Sometimes, a mark that represents 10^n is placed before a mark of one of the two next higher values (I before V or X; X before L or C; etc.). In this case, the value of the smaller mark is SUBTRACTED from the mark it precedes:

    • IV = 4
    • IX = 9
    • XL = 40
    This compound mark forms a unit and may not be combined to make another compound mark (e.g., IXL is wrong for 39; XXXIX is correct).

    Compound marks like XD, IC, and XM are not legal, since the smaller mark is too much smaller than the larger one. For XD (wrong for 490), one would use CDXC; for IC (wrong for 99), one would use XCIX; for XM (wrong for 990), one would use CMXC. 90 is expressed XC and not LXL, since L followed by X connotes that successive marks are X or smaller (probably, anyway).

    Given N (1 <= N < 3,500), the number of pages in the preface of a book, calculate and print the number of I's, V's, etc. (in order from lowest to highest) required to typeset all the page numbers (in Roman numerals) from 1 through N. Do not print letters that do not appear in the page numbers specified.

    If N = 5, then the page numbers are: I, II, III, IV, V. The total number of I's is 7 and the total number of V's is 2.

    PROGRAM NAME: preface

    INPUT FORMAT

    A single line containing the integer N.

    SAMPLE INPUT (file preface.in)

    5
    

    OUTPUT FORMAT

    The output lines specify, in ascending order of Roman numeral letters, the letter, a single space, and the number of times that letter appears on preface page numbers. Stop printing letter totals after printing the highest value letter used to form preface numbers in the specified set.

    SAMPLE OUTPUT (file preface.out)

    I 7
    V 2
    /*
    ID: mcdonne1
    PROG: preface
    LANG: C++
    */
    #include<cstdio>
    enum e{I,V,X,L,C,D,M};
    char r[7]={'I','V','X','L','C','D','M'};
    int n;
    int p[5],have[7];
    int v[7]={1,5,10,50,100,500,1000};
    void plus(int x)
    {
    	int cnt=4;
    	while(x)
    	{
    		p[cnt--]=x%10;
    		x/=10;
    	}
    	while(cnt<=4)
    	{
    		switch(cnt)
    		{
    			case 1:
    				have[M]+=p[cnt];
    				break;
    			case 2:
    				if(p[cnt]==9)
    				{
    					++have[M];
    					++have[C];
    				}
    				else if(p[cnt]<9&&p[cnt]>=5)
    				{
    					++have[D];
    					have[C]+=p[cnt]-5;
    				}
    				else if(p[cnt]==4)
    				{
    					++have[D];
    					++have[C];
    				}
    				else have[C]+=p[cnt];
    				break;
    			case 3:
    				if(p[cnt]==9)
    				{
    					++have[C];
    					++have[X];
    				}
    				else if(p[cnt]<9&&p[cnt]>=5)
    				{
    					++have[L];
    					have[X]+=p[cnt]-5;
    				}
    				else if(p[cnt]==4)
    				{
    					++have[L];
    					++have[X];
    				}
    				else have[X]+=p[cnt];
    				break;
    			case 4:
    				if(p[cnt]==9)
    				{
    					++have[X];
    					++have[I];
    				}
    				else if(p[cnt]<9&&p[cnt]>=5)
    				{
    					++have[V];
    					have[I]+=p[cnt]-5;
    				}
    				else if(p[cnt]==4)
    				{
    					++have[V];
    					++have[I];
    				}
    				else have[I]+=p[cnt];
    				break;
    		}
    		++cnt;
    	}
    }
    int main()
    {
    	freopen("preface.in","r",stdin);
    	freopen("preface.out","w",stdout);
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i) plus(i);
    	for(int i=0;i<=6;++i)
    		if(have[i]) printf("%c %d\n",r[i],have[i]);
    		else break;
    	return 0;
    }
    Subset Sums
    JRM

    For many sets of consecutive integers from 1 through N (1 <= N <= 39), one can partition the set into two sets whose sums are identical.

    For example, if N=3, one can partition the set {1, 2, 3} in one way so that the sums of both subsets are identical:

    • {3} and {1,2}

    This counts as a single partitioning (i.e., reversing the order counts as the same partitioning and thus does not increase the count of partitions).

    If N=7, there are four ways to partition the set {1, 2, 3, ... 7} so that each partition has the same sum:

    • {1,6,7} and {2,3,4,5}
    • {2,5,7} and {1,3,4,6}
    • {3,4,7} and {1,2,5,6}
    • {1,2,4,7} and {3,5,6}

    Given N, your program should print the number of ways a set containing the integers from 1 through N can be partitioned into two sets whose sums are identical. Print 0 if there are no such ways.

    Your program must calculate the answer, not look it up from a table.

    PROGRAM NAME: subset

    INPUT FORMAT

    The input file contains a single line with a single integer representing N, as above.

    SAMPLE INPUT (file subset.in)

    7
    

    OUTPUT FORMAT

    The output file contains a single line with a single integer that tells how many same-sum partitions can be made from the set {1, 2, ..., N}. The output file should contain 0 if there are no ways to make a same-sum partition.

    SAMPLE OUTPUT (file subset.out)

    4
    
    /*
    ID: mcdonne1
    PROG: subset
    LANG: C++
    */
    #include<cstdio>
    int n;
    int a[40]={0,0,0,1,1,0,0,4,7,0,0,35,62,0,0,361,657,0,0,4110,7636,0,0,49910,93846,0,0,632602,1199892,0,0,8273610,15796439,0,0,110826888,212681976,0,0,1512776590,};
    int main()
    {
    	freopen("subset.in","r",stdin);
    	freopen("subset.out","w",stdout);
    	scanf("%d",&n);
    	printf("%d\n",a[n]);
    	return 0;
    }
    Runaround Numbers

    Runaround numbers are integers with unique digits, none of which is zero (e.g., 81362) that also have an interesting property, exemplified by this demonstration:

    • If you start at the left digit (8 in our number) and count that number of digits to the right (wrapping back to the first digit when no digits on the right are available), you'll end up at a new digit (a number which does not end up at a new digit is not a Runaround Number). Consider: 8 1 3 6 2 which cycles through eight digits: 1 3 6 2 8 1 3 6 so the next digit is 6.
    • Repeat this cycle (this time for the six counts designed by the `6') and you should end on a new digit: 2 8 1 3 6 2, namely 2.
    • Repeat again (two digits this time): 8 1
    • Continue again (one digit this time): 3
    • One more time: 6 2 8 and you have ended up back where you started, after touching each digit once. If you don't end up back where you started after touching each digit once, your number is not a Runaround number.

    Given a number M (that has anywhere from 1 through 9 digits), find and print the next runaround number higher than M, which will always fit into an unsigned long integer for the given test data.

    PROGRAM NAME: runround

    INPUT FORMAT

    A single line with a single integer, M

    SAMPLE INPUT (file runround.in)

    81361
    

    OUTPUT FORMAT

    A single line containing the next runaround number higher than the input value, M.

    SAMPLE OUTPUT (file runround.out)

    81362
    
    /*
    ID: mcdonne1
    PROG: runround
    LANG: C++
    */
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,m,c;
    int num[11],v1[11],v2[11];
    void turn()
    {
    	register int j=m;
    	for(int i=1;i<j;++i)
    		swap(num[i],num[j--]);
    }
    bool review(int x)
    {
    	int vis[10];
    	memset(vis,0,sizeof(vis));
    	while(x)
    	{
    		if(x%10==0) return false;
    		if(vis[x%10]) return false;
    		vis[x%10]=1;
    		x/=10;
    	}
    	return true;
    }
    bool check(int x)
    {
    	memset(num,0,sizeof(num));
    	memset(v1,0,sizeof(v1));
    	memset(v2,0,sizeof(v2));
    	m=1;
    	while(x)
    	{
    		if(v1[(num[m]=x%10)]) return false;
    		v1[num[m++]]=true;
    		x/=10;
    	}
    	--m;
    	turn();
    	c=1;
    	while(!v2[num[c]])
    	{
    		v2[num[c]]=1;
    		c+=num[c]%m;
    		if(c>m)
    		c%=m;
    	}
    	if(num[c]!=num[1]) return false;
    	for(int i=1;i<=m;++i)
    		if(!v2[num[i]]) return false;
    	return true;
    }
    int main()
    {
    	freopen("runround.in","r",stdin);
    	freopen("runround.out","w",stdout);
        scanf("%d",&n);
        for(int i=n+1;;++i)
    		if(review(i)&&check(i))
    		{
    			printf("%d\n",i);
    			return 0;
    		}
    }
    Party Lamps
    IOI 98

    To brighten up the gala dinner of the IOI'98 we have a set of N (10 <= N <= 100) colored lamps numbered from 1 to N.

    The lamps are connected to four buttons:

    • Button 1: When this button is pressed, all the lamps change their state: those that are ON are turned OFF and those that are OFF are turned ON.
    • Button 2: Changes the state of all the odd numbered lamps.
    • Button 3: Changes the state of all the even numbered lamps.
    • Button 4: Changes the state of the lamps whose number is of the form 3xK+1 (with K>=0), i.e., 1,4,7,...

    A counter C records the total number of button presses.

    When the party starts, all the lamps are ON and the counter C is set to zero.

    You are given the value of counter C (0 <= C <= 10000) and the final state of some of the lamps after some operations have been executed. Write a program to determine all the possible final configurations of the N lamps that are consistent with the given information, without repetitions.

    PROGRAM NAME: lamps

    INPUT FORMAT

    No lamp will be listed twice in the input.

    Line 1:N
    Line 2:Final value of C
    Line 3:Some lamp numbers ON in the final configuration, separated by one space and terminated by the integer -1.
    Line 4:Some lamp numbers OFF in the final configuration, separated by one space and terminated by the integer -1.

    SAMPLE INPUT (file lamps.in)

    10
    1
    -1
    7 -1
    

    In this case, there are 10 lamps and only one button has been pressed. Lamp 7 is OFF in the final configuration.

    OUTPUT FORMAT

    Lines with all the possible final configurations (without repetitions) of all the lamps. Each line has N characters, where the first character represents the state of lamp 1 and the last character represents the state of lamp N. A 0 (zero) stands for a lamp that is OFF, and a 1 (one) stands for a lamp that is ON. The lines must be ordered from least to largest (as binary numbers).

    If there are no possible configurations, output a single line with the single word `IMPOSSIBLE'

    SAMPLE OUTPUT (file lamps.out)

    0000000000
    0101010101
    0110110110
    
    In this case, there are three possible final configurations:
    • All lamps are OFF
    • Lamps 1, 3, 5, 7, 9 are OFF and lamps 2, 4, 6, 8, 10 are ON.
    • Lamps 1, 4, 7, 10 are OFF and lamps 2, 3, 5, 6, 8, 9 are ON.
    /*
    ID: mcdonne1
    PROG: lamps
    LANG: C++
    */
    #include<cstdio>
    enum e{off=-1,null,on};
    int n,c,x;
    int p[100],f[100];
    int cz[9]={0,1,2,1,1,2,1,2,0};
    int at[9][6]={{},{-1,-1,-1,-1,-1,-1},{-1,-1,1,1,1,-1},{-1,1,-1,1,-1,1},{-1,1,1,-1,1,1},{1,-1,-1,1,-1,-1},{1,-1,1,-1,1,-1},{1,1,-1,-1,-1,1},{1,1,1,1,1,1}};
    int main()
    {
    	freopen("lamps.in","r",stdin);
    	freopen("lamps.out","w",stdout);
    	scanf("%d%d",&n,&c);
    	while(scanf("%d",&x)&&x!=-1) p[x-1]=on;
    	while(scanf("%d",&x)&&x!=-1) p[x-1]=off;
    	bool put=false;
    	for(int i=1;i<=8;++i)
    	{
    		for(int j=0;j<n;++j) f[j]=at[i][j%6];
    		bool g=true;
    		for(int j=0;j<n;++j)
    			if(p[j]!=null&&f[j]!=p[j])
    			{
    				g=false;
    				break;
    			}
    		if(g&&(c-cz[i]==0||c-cz[i]>1))
    		{
    			for(int j=0;j<n;++j) printf(f[j]==1 ? "1" : "0");
    			putchar('\n');
    			put=true;
    		}
    	}
    	if(!put) printf("IMPOSSIBLE\n");
    	return 0;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
USACO2022金组是国际在线判题系统USACO的最高级别,题目难度较高,在该比赛中取得好成绩是一项巨大的成就。以下是对该比赛的一些题目解析。 第一题:“交通计划” 题目要求:给定一个n个节点的有向图,每条边有一个长度,希望添加最少的边使得所有节点连通,求最小生成树的权值和。 解析:该题可以使用Kruskal算法求解,将每条边按权值从小到大排序,再依次加入,判断加入的边是否会形成环,若形成则不加入,直到所有节点连通为止。此时Kruskal算法得到的最小生成树的权值和即为所求。 第二题:“点火计划” 题目要求:给定一个n个节点的有向图,每条边有一个权值和一个点火时长,每个节点有一个点火启动时刻和时刻结束时刻,希望从其中选出一些边点火,使得所有节点都可从点火的边出发到达,且所选点火边的总点火时长最小。 解析:该题可以使用最小费用最大流算法求解。将每条边看做一个容量为1,费用为点火时长的边,源点向节点的点火边容量为1,费用为0的边,节点的点火边向汇点的容量为1,费用为0的边,对这个网络进行最小费用最大流即可得到所选边的总点火时长最小。 第三题:“美味佳肴” 题目要求:给定n个菜品,每个菜品有它的权值和两个类别,希望选出k个菜品,使得选出的菜品数量在每个类别中都不超过$\frac{k}{3}$个,且所选菜品的权值和最大。 解析:该题可以使用动态规划求解。设$f[i][j][k]$表示前i个菜品中,选择j个一类菜品,选择k个二类菜品的最大权值和,状态转移方程为$f[i][j][k]=max(f[i-1][j][k],f[i-1][j-1][k]+a[i],f[i-1][j][k-1]+b[i])$,其中a[i]为i号菜品的权值,若为一类则为该权值,否则为0,b[i]为i号菜品的权值,若为二类则为该权值,否则为0。最终答案为$f[n][$k/3$][$k/3$]。 以上是对USACO2022金组的部分题目的解析,USACO比赛是全球范围内的计算机竞赛,竞争非常激烈,能够在该比赛中脱颖而出是一项非常棒的成就。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值