# 2018SCUACM Training 4 校赛练习赛

emmmm我尽量？

------------------------------------------------------分割线-----------------------------------------------------

## A - Circular Area

Your task is to write a program, which, given two circles, calculates the area of their intersection with the accuracy of three digits after decimal point.
Input
In the single line of input file there are space-separated real numbers x1 y1 r1 x2 y2 r2. They represent center coordinates and radii of two circles.
Output
The output file must contain single real number - the area.
Sample Input
20.0 30.0 15.0 40.0 30.0 30.0
Sample Output
608.366

//%lf输出会wa
#include<cstdio>
#include<cmath>
int main()
{
double x1,y1,r1,x2,y2,r2,d,ans;
const double pi = 3.141592653;
while(scanf("%lf%lf%lf%lf%lf%lf",&x1,&y1,&r1,&x2,&y2,&r2) != EOF)
{
d = sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
if(d >= r1+r2)
ans = 0;
else if(fabs(r1-r2) >= d)
{
double r = r1 < r2 ? r1 : r2;
ans = pi*r*r;
}
else
{
double a, b;
a = acos((r1*r1+d*d-r2*r2)/(2*r1*d));
b = acos((r2*r2+d*d-r1*r1)/(2*r2*d));
ans = a*r1*r1+b*r2*r2-d*r1*sin(a);
}
printf("%.3f\n",ans);
}
return 0;
}

## B - Coins

Whuacmers use coins.They have coins of value A1,A2,A3...An Silverland dollar. One day Hibix opened purse and found there were some coins. He decided to buy a very nice watch in a nearby shop. He wanted to pay the exact price(without change) and he known the price would not more than m.But he didn't know the exact price of the watch.

You are to write a program which reads n,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to the number of Tony's coins of value A1,A2,A3...An then calculate how many prices(form 1 to m) Tony can pay use these coins.
InputThe input contains several test cases. The first line of each test case contains two integers n(1 ≤ n ≤ 100),m(m ≤ 100000).The second line contains 2n integers, denoting A1,A2,A3...An,C1,C2,C3...Cn (1 ≤ Ai ≤ 100000,1 ≤ Ci ≤ 1000). The last test case is followed by two zeros.OutputFor each test case output the answer on a single line.Sample Input
3 10
1 2 4 2 1 1
2 5
1 4 2 1
0 0
Sample Output
8
4

n种物品选择，有数量限制，显然是一个多重背包问题。

（我知道这句话可能有点拗口，但是我找不到更好的表达，而且我觉得这句话深究起来实际上还是错的，不过也能勉强将就一下啦。。。emmmm所以还是自己理解吧，反正只要记住一句话：dp[i]=i表示在已有的硬币中能凑出i的价值）

void complete_bag(int value)
{
for(int i = value; i <= m; i++)
dp[i] = max(dp[i], dp[i-value]+value);
}

for(int i = 1; i <= c[i]; i++)
{
for(int j = m; j >= i*a[i]; j--)
dp[j] = max(dp[j], dp[j-a[i]] + a[i]);
}

（思考一下为什么完全背包问题中循环的写法是i++，而这里是j--？这种写法能不能改？）

（我都这么问了肯定就不能改了对吧emmmm，因为完全背包问题对数目没有限制，所以对于取k个硬币的状态k，可以从状态k-1中再取一个硬币转换而来，所以只要先更新完前面的，后面的就可以直接更新了。而01背包问题中，取k-1个和取k个是相互独立的，需要单独计算）

（我知道我这里又没说清楚emmmm如果读3遍还读不通的话就自己理解吧。。。不然看我这段话容易跑偏emmmm）

void zeroone_bag(int value)
{
for(int i = m; i >= value; i--)
dp[i] = max(dp[i], dp[i-value]+value);
}
for(int i = 1; i <= c[idx]; i <<= 1)//二进制优化
{
zeroone_bag(i*a[idx]);
c[idx] -= i;
}
if(c[idx])
for(int i = 1; i <= c[idx]; i++)
zeroone_bag(a[idx]);

（其实总结这一段第一次写写的更好，但是我忘了怎么写的了。。。以后写博客一定要记得手动保存。）

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 105
#define maxm 100005
using namespace std;
int n,m;
int a[maxn],c[maxn];
int dp[maxm];//dp[i]:能否凑出i元
void complete_bag(int value)
{
for(int i = value; i <= m; i++)
dp[i] = max(dp[i], dp[i-value]+value);
}
void zeroone_bag(int value)
{
for(int i = m; i >= value; i--)
dp[i] = max(dp[i], dp[i-value]+value);
}
void multiple_bag(int idx)
{
if(a[idx]*c[idx] >= m)//完全背包问题
complete_bag(a[idx]);
else//01背包问题
{
for(int i = 1; i <= c[idx]; i <<= 1)//二进制优化
{
zeroone_bag(i*a[idx]);
c[idx] -= i;
}
if(c[idx])
for(int i = 1; i <= c[idx]; i++)
zeroone_bag(a[idx]);
}
}
int main()
{
while(scanf("%d%d",&n,&m) != EOF && (n || m))
{
memset(dp,0,sizeof(dp));
for(int i = 0; i < n; i++)
scanf("%d",&a[i]);
for(int i = 0; i < n; i++)
scanf("%d",&c[i]);
for(int i = 0; i < n; i++)
multiple_bag(i);
int ans = 0;
for(int i = 1; i <= m; i++)
if(dp[i] == i)
ans++;
printf("%d\n",ans);
}
return 0;
}


## C - Number Sequence

A number sequence is defined as follows:

f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.

Given A, B, and n, you are to calculate the value of f(n).
InputThe input consists of multiple test cases. Each test case contains 3 integers A, B and n on a single line (1 <= A, B <= 1000, 1 <= n <= 100,000,000). Three zeros signal the end of input and this test case is not to be processed.
OutputFor each test case, print the value of f(n) on a single line.
Sample Input
1 1 3
1 2 10
0 0 0
Sample Output
2
5

A和B都是定值，所以f(n)的取值就取决于f(n-1)与f(n-2)的组合。显然f(n)的值域为0到6共7种可能，所以其组合的种类有49，那么49一定是一个周期。至于有没有更小的周期，我们不需要考虑也没法考虑，只知道即便有更小的周期，也一定是49的因数就是了。

//陷阱：a%7 = b%7 = 0时无周期，因为前两个是1，后面全部是0
//A了因为数据弱

#include<cstdio>
int main()
{
int a,b,n;
int f[55];
while(scanf("%d%d%d",&a,&b,&n) && (a||b||n))
{
a %= 7;
b %= 7;
f[1] = f[2] = 1;
for(int i = 3; i <=50; i++)
f[i] = (a*f[i-1]%7+b*f[i-2]%7)%7;
printf("%d\n",f[n%49]);
}
return 0;
}

## D - Pashmak and Buses

Recently Pashmak has been employed in a transportation company. The company has kbuses and has a contract with a school which has n students. The school planned to take the students to d different places for d days (each day in one place). Each day the company provides all the buses for the trip. Pashmak has to arrange the students in the buses. He wants to arrange the students in a way that no two students become close friends. In his ridiculous idea, two students will become close friends if and only if they are in the same buses for all d days.

Please help Pashmak with his weird idea. Assume that each bus has an unlimited capacity.

Input

The first line of input contains three space-separated integers n, k, d (1 ≤ n, d ≤ 1000; 1 ≤ k ≤ 109).

Output

If there is no valid arrangement just print -1. Otherwise print d lines, in each of them print n integers. The j-th integer of the i-th line shows which bus the j-th student has to take on the i-th day. You can assume that the buses are numbered from 1 to k.

Examples
Input
3 2 2

Output
1 1 2
1 2 1

Input
3 2 1

Output
-1

Note

Note that two students become close friends only if they share a bus each day. But the bus they share can differ from day to day.

1 1

1 2

1 3

2 1

2 2

2 3

3 1

3 2

3 3

0 0

0 1

0 2

1 0

1 1

1 2

2 0

2 1

2 2

#include<cstdio>
#include<cstring>
#define maxn 1005
#define maxd 1005
using namespace std;
int n,k,d;
int bus[maxn][maxd];
void trans(int i)
{
int t = i, idx = 0;
while(t)
{
bus[i][idx++] = t%k;
t/=k;
}
}
int main()
{
while(scanf("%d%d%d",&n,&k,&d) != EOF)
{
int s = 1;
for(int i = 0; i < d; i++)
{
s *= k;
if(s >= n)
break;
}
if(s < n)
printf("-1\n");
else if(k == 1 && n == 1)//没有1进制
{
while(d--)
printf("1\n");
}
else
{
memset(bus, 0, sizeof(bus));
for(int i = 0; i < n; i++)//第i个人d天内的乘车方案
trans(i);
for(int i = 0; i < d; i++)
{
for(int j = 0; j < n-1; j++)
printf("%d ", bus[j][i]+1);
printf("%d\n",bus[n-1][i]+1);
}
}
}
return 0;
}

## E - Rescue

Angel was caught by the MOLIGPY! He was put in prison by Moligpy. The prison is described as a N * M (N, M <= 200) matrix. There are WALLs, ROADs, and GUARDs in the prison.

Angel's friends want to save Angel. Their task is: approach Angel. We assume that "approach Angel" is to get to the position where Angel stays. When there's a guard in the grid, we must kill him (or her?) to move into the grid. We assume that we moving up, down, right, left takes us 1 unit time, and killing a guard takes 1 unit time, too. And we are strong enough to kill all the guards.

You have to calculate the minimal time to approach Angel. (We can move only UP, DOWN, LEFT and RIGHT, to the neighbor grid within bound, of course.)
InputFirst line contains two integers stand for N and M.

Then N lines follows, every line has M characters. "." stands for road, "a" stands for Angel, and "r" stands for each of Angel's friend.

Process to the end of the file.
OutputFor each test case, your program should output a single integer, standing for the minimal time needed. If such a number does no exist, you should output a line containing "Poor ANGEL has to stay in the prison all his life."
Sample Input
7 8
#.#####.
#.a#..r.
#..#x...
..#..#.#
#...##..
.#......
........
Sample Output
13

#include<cstdio>
#include<cstring>
#define maxn 205
#define maxm 205
char map[maxn][maxm];
int book[maxn][maxm];//0表示起点，-1表示不可达点，其他正数表示到达该点的最小步数
int quex[maxn*maxm];
int quey[maxn*maxm];
int n,m,x,y,dx,dy;
int main()
{
while(scanf("%d%d",&n,&m) != EOF)
{
for(int i = 0; i < n; i++)
{
getchar();
for(int j = 0; j < m; j++)
{
map[i][j] = getchar();
if(map[i][j] == 'a')//起点
{
x = i;
y = j;
}
else if(map[i][j] == 'r')//终点
{
dx = i;
dy = j;
}
}
}
tail = 1;
memset(book,-1,sizeof(book));
quex[0] = x;
quey[0] = y;
book[x][y] = 0;
int nx[] = {0,1,0,-1};
int ny[] = {1,0,-1,0};
{
//出队
for(int i = 0; i < 4; i++)
{
int tx = x+nx[i];
int ty = y+ny[i];
//地图越界
if(tx < 0 || tx >= n || ty < 0 || ty >= m)
continue;
//围墙
if(map[tx][ty] == '#')
continue;
int step = book[x][y] + 1;
if(map[tx][ty] == 'x')
step++;
//更远的路径
if(book[tx][ty] != -1 && step >= book[tx][ty])
continue;
//入队
quex[tail] = tx;
quey[tail] = ty;
book[tx][ty] = step;
tail++;
}
}
if(book[dx][dy] == -1)
printf("Poor ANGEL has to stay in the prison all his life.\n");
else
printf("%d\n",book[dx][dy]);
}
return 0;
}

## F - 训练


Time Limit: 1000 MS    Memory Limit: 131072 K



## Sample Input

32 101 51 7102 995 294 828 723 868 243 697 443 792 19

## Sample Output

17515

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define maxn 100005
using namespace std;
typedef struct
{
int d,p;
} node;
bool cmp(node a, node b)
{
return a.d > b.d;
}
node a[maxn];
priority_queue<int> que;
int main()
{
long long n,max,date,index;
while(scanf("%d",&n) != EOF)
{
for(int i = 0; i < n; i++)
scanf("%d%d",&a[i].d,&a[i].p);
sort(a,a+n,cmp);
date = n;
max = index = 0;
while(date > 0)
{
while(a[index].d >= date)
que.push(a[index++].p);
if(!que.empty())
{
int t = que.top();
que.pop();
max += t;
}
date--;
}
while(!que.empty())
que.pop();
printf("%lld\n",max);
}
return 0;
}

## G - Yukari's Birthday

Today is Yukari's n-th birthday. Ran and Chen hold a celebration party for her. Now comes the most important part, birthday cake! But it's a big challenge for them to place n candles on the top of the cake. As Yukari has lived for such a long long time, though she herself insists that she is a 17-year-old girl.
To make the birthday cake look more beautiful, Ran and Chen decide to place them like r ≥ 1 concentric circles. They place k i candles equidistantly on the i-th circle, where k ≥ 2, 1 ≤ i ≤ r. And it's optional to place at most one candle at the center of the cake. In case that there are a lot of different pairs of r and k satisfying these restrictions, they want to minimize r × k. If there is still a tie, minimize r.
InputThere are about 10,000 test cases. Process to the end of file.
Each test consists of only an integer 18 ≤ n ≤ 10 12
OutputFor each test case, output r and k.Sample Input
18
111
1111
Sample Output
1 17
2 10
3 10

#include<cstdio>
#include<iostream>
#include<algorithm>
#define inf 0xfffffff
using namespace std;
typedef long long ll;
int main()
{
ll n;
while(cin>>n)
{
//通解r=1,k=n-1,即中间放一根，外面一个圆放n-1根
ll minr = 1, mink = n-1;
for(ll r = 1; r <= 40; r++)
{
ll lk = 2, rk = n;
while(lk <= rk)//二分
{
ll midk = (lk+rk)/2;
ll t = 1, sum = 0;//计算左边等式
for(ll i = 0; i < r; i++)
{
if(n/midk < t)//t马上超过n了（其实是t*mid可能炸long long）
{
sum = n+1;//相当于告诉后面等式不可能成立
break;
}
t *= midk;
sum += t;
if(sum > n)//左边已经超过n了，等式不成立
break;
}
if(sum < n-1)
lk = midk+1;
else if(sum > n)
rk = midk-1;
else
{
if(r*midk < minr*mink)
{
minr = r;
mink = midk;
}
rk = midk-1;
}
}
}
cout<<minr<<" "<<mink<<endl;
}
return 0;
}

## H - Tempter of the Bone

The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the ground sinking. He realized that the bone was a trap, and he tried desperately to get out of this maze.

The maze was a rectangle with sizes N by M. There was a door in the maze. At the beginning, the door was closed and it would open at the T-th second for a short period of time (less than 1 second). Therefore the doggie had to arrive at the door on exactly the T-th second. In every second, he could move one block to one of the upper, lower, left and right neighboring blocks. Once he entered a block, the ground of this block would start to sink and disappear in the next second. He could not stay at one block for more than one second, nor could he move into a visited block. Can the poor doggie survive? Please help him.
InputThe input consists of multiple test cases. The first line of each test case contains three integers N, M, and T (1 < N, M < 7; 0 < T < 50), which denote the sizes of the maze and the time at which the door will open, respectively. The next N lines give the maze layout, with each line containing M characters. A character is one of the following:

'X': a block of wall, which the doggie cannot enter;
'S': the start point of the doggie;
'D': the Door; or
'.': an empty block.

The input is terminated with three 0's. This test case is not to be processed.
OutputFor each test case, print in one line "YES" if the doggie can survive, or "NO" otherwise.
Sample Input
4 4 5
S.X.
..X.
..XD
....
3 4 5
S.X.
..X.
...D
0 0 0
Sample Output
NO
YES

#include<iostream>
#include<cstring>
#include<cmath>
#define inf 0xffffff
#define maxn 10
#define maxm 10
using namespace std;
char map[maxn][maxm];
int book[maxn][maxm];
int n,m,t;
int sx, sy, ex, ey;
int dfs(int x, int y, int step) {
if(map[x][y] == 'D')
{
if(step == 0)
return 1;
return 0;
}
int dx[] = {1,0,-1,0};
int dy[] = {0,1,0,-1};
int t = 0;
for(int i = 0; i < 4; i++) {
int nx = x+dx[i];
int ny = y+dy[i];
if(nx < 0 || nx >= n
|| ny < 0 || ny >= m
|| book[nx][ny] != 0
|| map[nx][ny] == 'X')
continue;
book[nx][ny] = 1;
t = dfs(nx,ny,step-1);
if(t) return 1;
book[nx][ny] = 0;
}
return 0;
}
int main() {
while(cin>>n>>m>>t) {
if(!(n || m || t))
break;
int wallCnt = 0;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++) {
cin>>map[i][j];
if(map[i][j] == 'S') {
sx = i;
sy = j;
}
else if(map[i][j] == 'D') {
ex = i;
ey = j;
}
else if(map[i][j] == 'X')
wallCnt++;
}
if(abs(sx-ex)+abs(sy-ey) < t)//距离剪枝
cout<<"NO"<<endl;
else if((abs(sx-ex)+abs(sy-ey)+t) & 1)//奇偶剪枝
cout<<"NO"<<endl;
else if(m*n-wallCnt <= t)//数量剪枝
cout<<"NO"<<endl;
else {
memset(book,0,sizeof(book));
book[sx][sy] = 1;
int step = dfs(sx,sy,t);
book[sx][sy] = 0;
if(step) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
return 0;
}


• 写评论