ICPC训练联盟2021寒假冬令营(3)(部分题解):

ICPC训练联盟2021寒假冬令营(3)(部分题解):


C - Simple division
Integer division between a dividend n and a divisor d yields a quotient q and a remainder r. q is the integer which maximizes q ∗ d
such that q ∗ d ≤ n and r = n − q ∗ d.
For any set of integers there is an integer d such that each of the
given integers when divided by d leaves the same remainder.
Input
Each line of input contains a sequence of nonzero integer numbers
separated by a space. The last number on each line is 0 and this
number does not belong to the sequence. There will be at least 2 and
no more than 1000 numbers in a sequence; not all numbers occuring
in a sequence are equal. The last line of input contains a single 0
and this line should not be processed.
Output
For each line of input, output the largest integer which when divided into each of the input integers
leaves the same remainder.
Sample Input
701 1059 1417 2312 0
14 23 17 32 122 0
14 -22 17 -31 -124 0
0
Sample Output
179
3
3
题意:给出一组数,然后让你求一个数,使得这组数中的每一个数除以你的解所得到的余数相同
两个不同的数除以同一个数,若他们余数相同,则这两个数的差值是他们共同除数的整数倍,我们将这组数两两相减,将得到的所有差值求最大公约数即可得出结果
代码:

#include<iostream>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
#define N 100005
typedef long long int ll;
int gcd(int a,int b){
    if(a>b) swap(a,b);
    if(a==0) return b;
    else return gcd(a,b%a);
}
int main(){
    int n;
    while(cin>>n&&n)
    {
        int a[N];
        a[0]=n;
        int i=1;
        while (1)
        {
            cin>>a[i];
            if(!a[i]) break;
            i++;
        }
        sort(a,a+i);
        int res=a[1]-a[0];
        for(int j=2;j<i;j++){
            if(a[j]-a[j-1]!=res)
            res=gcd(res,a[j]-a[j-1]);
        }
        cout<<res<<endl;
    }
    return 0;
}

E - Dead Fraction
Mike is frantically scrambling to finish his thesis at the last minute. He needs to assemble all his research notes into vaguely coherent form in the next 3 days. Unfortunately, he notices that he had been extremely sloppy in his calculations. Whenever he needed to perform arithmetic, he just plugged it into a calculator and scribbled down as much of the answer as he felt was relevant. Whenever a repeating fraction was displayed, Mike simply reccorded the first few digits followed by “…”. For instance, instead of “1/3” he might have written down “0.3333…”. Unfortunately, his results require exact fractions! He doesn’t have time to redo every calculation, so he needs you to write a program (and FAST!) to automatically deduce the original fractions.
To make this tenable, he assumes that the original fraction is always the simplest one that produces the given sequence of digits; by simplest, he means the the one with smallest denominator. Also, he assumes that he did not neglect to write down important digits; no digit from the repeating portion of the decimal expansion was left unrecorded (even if this repeating portion was all zeroes).
Input
There are several test cases. For each test case there is one line of input of the form “0.dddd…” where dddd is a string of 1 to 9 digits, not all zero. A line containing 0 follows the last case.
Output
For each case, output the original fraction.
Sample Input
0.2…
0.20…
0.474612399…
0
Sample Output
2/9
1/5
1186531/2500000
Hint
Note that an exact decimal fraction has two repeating expansions (e.g. 1/5 = 0.2000… = 0.19999…).
题意:把循环小数转换成原分数,比如:0.333…=>1/3,且循环小数中可以看成不同的循环节,输出结果分母最小的情况,如0.16…若将6看成
循环节,则对应分数为1/6,若将16看成循环节,则对应分数为16/99;
代码有注释,不多阐述了。
代码:

#include<iostream>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
#define N 1005
typedef long long int ll;
int gcd(int a,int b){
    if(a>b) swap(a,b);
    if(a==0) return b;
    else return gcd(a,b%a);
}
int main(){
    char s[N];
    while(scanf("%s",s)&&strcmp(s,"0")) //循环小数n个数字,循环节k个数字,n-k个非循环节数字
    {                                   //分母是k个9再补上n-k个0,分子是n个数字组成的数减去n-k个非循环数字组成的数
        int a=0;        //整个小数部分真值
        int n=0;        //小数部分的个数
        for(int i=2;i<strlen(s)-3;i++){
            a=a*10+s[i]-'0';	//a是n个循环数字组成的数
            n++;
        }
        int min_fz=INT_MAX,min_fm=INT_MAX;
        //枚举每一种循环节下的结果
        for(int b=a/10,i=n-1;i>=0;b/=10,i--)    //b代表非循环节部分的数字所组成的值,i代表非循环节的字数
        {
            int k=n-i;  //k代表循环节字数
            int fz=a-b; //分子
            int fm=0;   //分母
            for(int j=n-1;j>=n-k;j--)
                fm+=9*pow(10.0,j);
            int gd=gcd(fz,fm);  //求分子分母最大公约数并化简
            fz/=gd;fm/=gd;
            if(fm<min_fm){
                min_fz=fz;
                min_fm=fm;
            }
        }
        cout<<min_fz<<'/'<<min_fm<<endl;
    }
    return 0;
}

G - Coin Toss
In a popular carnival game, a coin is tossed onto a table with an area that is covered with square tiles in a grid. The prizes are determined by the number of tiles covered by the coin when it comes to rest: the more tiles it covers, the better the prize. In the following diagram, the results from five coin tosses are shown:

In this example:

coin 1 covers 1 tile
coin 2 covers 2 tiles
coin 3 covers 3 tiles
coin 4 covers 4 tiles
coin 5 covers 2 tiles
Notice that it is acceptable for a coin to land on the boundary of the playing area (coin 5). In order for a coin to cover a tile, the coin must cover up a positive area of the tile. In other words, it is not enough to simply touch the boundary of the tile. The center of the coin may be at any point of the playing area with uniform probability. You may assume that (1) the coin always comes to a rest lying flat, and (2) the player is good enough to guarantee that the center of the coin will always come to rest on the playing area (or the boundary).

The probability of a coin covering a certain number of tiles depends on the tile and coin sizes, as well as the number of rows and columns of tiles in the playing area. In this problem, you will be required to write a program which computes the probabilities of a coin covering a certain number of tiles.

Input
The first line of input is an integer specifying the number of cases to follow. For each case, you will be given 4 integers m, n, t, and c on a single line, separated by spaces. The playing area consists of m rows and n columns of tiles, each having side length t. The diameter of the coin used is c. You may assume that 1 <= m, n <= 5000, and 1 <= c < t <= 1000.
Output
For each case, print the case number on its own line. This is followed by the probability of a coin covering 1 tile, 2 tiles, 3 tiles, and 4 tiles each on its own line. The probability should be expressed as a percentage rounded to 4 decimal places. Use the format as specified in the sample output. You should use double-precision floating-point numbers to perform the calculations. “Negative zeros” should be printed without the negative sign.

Separate the output of consecutive cases by a blank line.
Sample Input
3
5 5 10 3
7 4 25 20
10 10 10 4
Sample Output
Case 1:
Probability of covering 1 tile = 57.7600%
Probability of covering 2 tiles = 36.4800%
Probability of covering 3 tiles = 1.2361%
Probability of covering 4 tiles = 4.5239%

Case 2:
Probability of covering 1 tile = 12.5714%
Probability of covering 2 tiles = 46.2857%
Probability of covering 3 tiles = 8.8293%
Probability of covering 4 tiles = 32.3135%

Case 3:
Probability of covering 1 tile = 40.9600%
Probability of covering 2 tiles = 46.0800%
Probability of covering 3 tiles = 2.7812%
Probability of covering 4 tiles = 10.1788%

题意:给一个mXn个正方形组成的矩形,给出正方形的边长,圆的直径,分别求硬币压在一块、两块、三块、四块正方形上的概率(在大矩形内)
题目意图很明显,我们需要求出每一种情况下圆心所能在的位置组成的面积占矩形总面积的比例,几何不好,求了老半天…
代码:

#include<iostream>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
#define N 200005
#define PI acos(-1.0)
typedef long long int ll;
int main(){
    int s;
    cin>>s;
    int cs=1;
    while(s--)
    {
        double m,n,t,c;
        double res[4];
        cin>>m>>n>>t>>c;
        res[0]=(t-c)*(t-c)*m*n+c*c+(m+n)*c*(t-c);//一块
        res[1]=c*(t-c/2)*(2*m+2*n-4)+c*(t-c)*((m-1)*(n-2)+(m-2)*(n-1));//两块
        res[2]=(c*c-PI*c*c/4)*(m-1)*(n-1);//三块
        res[3]=m*n*t*t-res[0]-res[1]-res[2];//四块
        printf("Case %d:\n",cs++);
        printf("Probability of covering 1 tile  = %.4f%%\n",res[0]*100.0/(m*n*t*t));
        for(int i=1;i<4;i++)
        printf("Probability of covering %d tiles = %.4f%%\n",i+1,res[i]*100.0/(m*n*t*t));
        cout<<endl;
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值