Rescue The Princess
Description
Several days ago, a beast caught a beautiful princess and the princess was put in prison. To rescue the princess, a prince who wanted to marry the princess set out immediately. Yet, the beast set a maze. Only if the prince find out the maze’s exit can he save the princess.
Input
The first line is an integer T(1 <= T <= 100) which is the number of test cases. T test cases follow. Each test case contains two coordinates A(x1,y1) and B(x2,y2), described by four floating-point numbers x1, y1, x2, y2 ( |x1|, |y1|, |x2|, |y2| <= 1000.0).
Output
For each test case, you should output the coordinate of C(x3,y3), the result should be rounded to 2 decimal places in a line.
Sample Input
4
-100.00 0.00 0.00 0.00
0.00 0.00 0.00 100.00
0.00 0.00 100.00 100.00
1.00 0.00 1.866 0.50
Sample Output
(-50.00,86.60) (-86.60,50.00) (-36.60,136.60) (1.00,1.00)
这道题题意,已知两个点,求逆时针方向的正三角形的另一个点的坐标;
我的思路是利用三角函数,和库函数直接求解,
1 #include<stdio.h>
2 #include<math.h>
3 #include<string.h>
4 #define PI 3.1415926
5 int main() 6 { 7 int T; 8 double R,x[3],y[3],len; 9 scanf("%d",&T); 10 while(T--) 11 { 12 scanf("%lf%lf%lf%lf",&x[0],&y[0],&x[1],&y[1]); 13 R=atan2(y[1]-y[0],x[1]-x[0]); 14 len=sqrt((y[1]-y[0])*(y[1]-y[0])+(x[1]-x[0])*(x[1]-x[0])); 15 x[2]=x[0]+len*cos(R+PI/3); 16 y[2]=y[0]+len*sin(R+PI/3); 17 printf("(%.2lf,%.2lf)\n",x[2],y[2]); 18 } 19 return 0; 20 }
首先,根据已知的两个点求斜率R=tan;然后是等边三角形的边长 len,因为本题是逆时针旋转的,所以可以在第一个点的基础上再逆时针旋转60°,若以A点为原点的话,所求点的坐标为(len*cos(R+PI/3),len*sin(R+PI/3))这是相对坐标,然后要记得要加上A是坐标,才是绝对坐标;
下面是第二种解法:
实际做题中我们可能会遇到很多有关及计算几何的问题,其中有一类问题就是向量的旋转问题,下面我们来具体探讨一下有关旋转的问题
首先我们先把问题简化一下,我们先研究一个点绕另一个点旋转一定角度的问题。已知A点坐标(x1,y1),B点坐标(x2,y2),我们需要求得A点绕着B点旋转θ度后的位置。
A点绕B点旋转θ角度后得到的点,问题是我们要如何才能得到A' 点的坐标。(向逆时针方向旋转角度正,反之为负)研究一个点绕另一个点旋转的问题,我们可以先简化为一个点绕原点旋转的问题,这样比较方便我们的研究。之后我们可以将结论推广到一般的形式上。
令B是原点,我们先以A点向逆时针旋转为例,我们过A' 做AB的垂线,交AB于C,过C做x轴的平行线交过A' 做x轴的垂线于D。过点C做x轴的垂线交x轴于点E。
令A的坐标(x,y),A' 坐标(x1,y1),B的坐标(0,0)。我们可以轻松的获取AB的长度,而且显而易见A' B长度等于AB。假设我们已知θ角的大小那么我们可以很快求出BC和A' C的长度。BC=A' B x cosθ,A' C=A' B x sinθ。
因为∠A' CB和∠DCE为直角(显然的结论),则∠A' CD +∠DCB =∠ECD +∠DCB=90度。
则∠A' CD=∠ECD,∠A' DC=∠CEB=90度,因此可以推断⊿CA' D ∽⊿CBE。由此可以退出的结论有:
BC/BE=A' C/A' D和BC/CE=A' C/CD
当然了DC和A' D都是未知量,需要我们求解,但是我们却可以通过求出C点坐标和E点坐标间接获得A' C和CD的长度。我们应该利用相似的知识求解C点坐标。
C点横坐标等于:((|AB| x cosθ) / |AB|) * x = x*cosθ
C点纵坐标等于:((|AB| x cosθ) / |AB|) * y = y*cosθ
则CE和BE的的长度都可以确定。
我们可以通过相⊿CA' D ∽⊿CBE得出:
AD = x * sinθ DC = y * sinθ
那么接下来很容易就可以得出
x1 = x*cosθ- y * sinθ y1 = y*cosθ + x * sinθ
则A' 的坐标为(x*cosθ- y * sinθ, y*cosθ + x * sinθ)
我们可以这样认为:对于任意点A(x,y),A非原点,绕原点旋转θ角后点的坐标为:(x*cosθ- y * sinθ, y*cosθ + x * sinθ)
接下来我们对这个结论进行一下简单的推广,对于任意两个不同的点A和B(对于求点绕另一个点旋转后的坐标时,A B重合显然没有太大意义),求A点绕B点旋转θ角度后的坐标,我们都可以将B点看做原点,对A和B进行平移变换,计算出的点坐标后,在其横纵坐标上分别加上原B点的横纵坐标,这个坐标就是A' 的坐标
推广结论:对于任意两个不同点A和B,A绕B旋转θ角度后的坐标为:
(Δx*cosθ- Δy * sinθ+ xB, Δy*cosθ + Δx * sinθ+ yB )
注:xB、yB为B点坐标。
结论的进一步推广:对于任意非零向量AB(零向量研究意义不大),对于点C进行旋转,我们只需求出点A和B对于点C旋转一定角度的坐标即可求出旋转后的向量A' B' ,因为
向量旋转后仍然是一条有向线段。同理,对于任意二维平面上的多边形旋转也是如此
附上学长代码:
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll __int64 #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 137 #define N 22 using namespace std; const int inf = 0x7f7f7f7f; const int mod = 1000000007; double xx1,yy1,xx2,yy2; int main() { // Read(); int T; scanf("%d",&T); while (T--) { scanf("%lf%lf%lf%lf",&xx1,&yy1,&xx2,&yy2); // printf("%.3lf %.3lf %.3lf %.3lf\n",xx1,yy1,xx2,yy2); double tx = xx2 - xx1; double ty = yy2 - yy1; double x = tx*(1.0/2.0) - ty*(sqrt(3.0)/2.0) + xx1; double y = ty*(1.0/2.0) + tx*(sqrt(3.0)/2.0) + yy1; printf("(%.2lf,%.2lf)\n",x,y); } return 0; }
虽然自己还有点不太理解;不过先存着再说哈,,,
那么下面是第二题:
We never paid any heed to the ancient prophecies, like fools we clung to the old hatreds, and fought as we had for generations. Until one day the sky rained fire, and a new enemy came upon us. We stand now upon the brink of destruction, for the Reign of Chaos has come at last.
Thrall, the warchief of the Orcish Horde, all along, he led his tribe live in the fringe of Lordaeron under the human control. In a downpour night, Thrall falls into sleep in a Orc hall at Arathi Highlands, at this moment he heard a voice:
“The sands of time have run out, son of Durotan. The cries of war echo upon the winds, the remnants of the past scar the land which is besieged once again by conflict. Heroes arise to challenge fate, and lead their brethren to battle. As mortal armies rush blindly towards their doom, The Burning Shadow comes to consume us all. You must rally the Horde, and lead your people to their destiny.
I will answer all of your questions in time, young warchief. For now, rally your warriors and prepare to leave this land, cross the sea to the distant land of Kalimdor. We will speak again. ”
Thrall believes the prophesy of Blood Raven Medivh. Three days later, He and Grom Hellscream's Warsong Clan meet in the Lordaeron coast to the distant lands of Kalimdor. But the Goblin Zeppelins they take encountered storms in the middle. Thrall and Grom falling to the islands, they want to find each other and then to Kalimdor.
For the sake of simplicity, we assume that Thrall and Grom may fall into any islands x and y, only by Thrall to find Grom or by Grom to find Thrall. Give you the map of this island, please judge that Thrall and Gtom can meet?
2 3 2 1 2 1 3 3 2 1 2 2 3
Case 1: The Burning Shadow consume us all Case 2: Kalimdor is just ahead
思路:枚举每个点,然后bfs就可以了
附代码
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll __int64 #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 10007 #define N 2007 using namespace std; const int inf = 0x7f7f7f7f; const int mod = 1000000007; struct node { int v; int next; }g[M]; int head[N],ct; bool ok[N][N]; bool vt[N]; int n,m; void add(int u,int v) { g[ct].v = v; g[ct].next = head[u]; head[u] = ct++; } void bfs(int s) { int i; for (i = 1; i <= n; ++i) vt[i] = false; vt[s] = true; queue<int> Q; Q.push(s); while (!Q.empty()) { int u = Q.front(); Q.pop(); for (i = head[u]; i != -1; i = g[i].next) { int v = g[i].v; if (!vt[v]) { vt[v] = true; ok[s][v] = true; Q.push(v); } } } } int main() { // Read(); int T; int i,j; scanf("%d",&T); int cas = 1; while (T--) { scanf("%d%d",&n,&m); CL(head,-1); ct = 0; int x,y; for (i = 0; i < m; ++i) { scanf("%d%d",&x,&y); add(x,y); } CL(ok,false); for (i = 1; i <= n; ++i) ok[i][i] = true; for (i = 1; i <= n; ++i) bfs(i); bool flag = false; for (i = 1; i <= n && !flag; ++i) { for (j = 1; j <= n && !flag; ++j) { if (ok[i][j] || ok[j][i]) continue; else { flag = true; break; } } } if (!flag) printf("Case %d: Kalimdor is just ahead\n",cas++); else printf("Case %d: The Burning Shadow consume us all\n",cas++); } return 0; }
那么下一题
Description
It's easy for ACMer to calculate A^X mod P. Now given seven integers n, A, K, a, b, m, P, and a function f(x) which defined as following.
f(x) = K, x = 1
f(x) = (a*f(x-1) + b)%m , x > 1
Now, Your task is to calculate
( A^(f(1)) + A^(f(2)) + A^(f(3)) + ...... + A^(f(n)) ) modular P.
Input
In the first line there is an integer T (1 < T <= 40), which indicates the number of test cases, and then T test cases follow. A test case contains seven integers n, A, K, a, b, m, P in one line.
1 <= n <= 10^6
0 <= A, K, a, b <= 10^9
1 <= m, P <= 10^9
Output
For each case, the output format is “Case #c: ans”.
c is the case number start from 1.
ans is the answer of this problem.
Sample Input
2 3 2 1 1 1 100 100 3 15 123 2 3 1000 107
Sample Output
Case #1: 14 Case #2: 63
题意:
题意很简单,看题就知道。 A^X % P
思路:
在求A^X 幂时,快速幂求的话,是O(10^6*log(n)*40) = O(10^9) 肯定会超时,
我们将X转化成 x = i*k + j。这样先在数组可以表示的范围内找到一个k,然后保存A^(1-k)的值,然后再将求出(A^k)^i 保存在数组里,这样每次求A^x,便可以通过这两个数组在O(1)的时间复杂度内求出来,这样时间复杂度就变成了O(10^6*40) = O(4*10^7)了
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 33333 #define N 31622 using namespace std; const int mod = 1000000007; ll powB[M + 10]; ll powA[N + 10]; ll n, A, K, a, b, m, P; void init() { powA[0] = 1; for (int i = 1; i <= N; ++i) { powA[i] = powA[i - 1]*A%P; } ll tmp = powA[N]; powB[0] = 1; for (int i = 1; i <= M; ++i) { powB[i] = powB[i - 1]*tmp%P; } } void solve(int cas) { ll fx = K; ll ans = 0; for (int i = 1; i <= n; ++i) { ans = (ans + powB[fx/N]*powA[fx%N]%P)%P; fx = (a*fx + b)%m; } printf("Case #%d: %lld\n",cas++,ans); } int main() { int T; int cas = 1; scanf("%d",&T); while (T--) { cin>>n>>A>>K>>a>>b>>m>>P; init(); solve(cas++); } return 0; }
接下来
Description
Alice and Bob like playing games very much.Today, they introduce a new game.
There is a polynomial like this: (a0*x^(2^0)+1) * (a1 * x^(2^1)+1)*.......*(an-1 * x^(2^(n-1))+1). Then Alice ask Bob Q questions. In the expansion of the Polynomial, Given an integer P, please tell the coefficient of the x^P.
Can you help Bob answer these questions?
Input
The first line of the input is a number T, which means the number of the test cases.
For each case, the first line contains a number n, then n numbers a0, a1, .... an-1 followed in the next line. In the third line is a number Q, and then following Q numbers P.
1 <= T <= 20
1 <= n <= 50
0 <= ai <= 100
Q <= 1000
0 <= P <= 1234567898765432
Output
For each question of each test case, please output the answer module 2012.
Sample Input
1 2 2 1 2 3 4
Sample Output
2 0
Hint
The expansion of the (2*x^(2^0) + 1) * (1*x^(2^1) + 1) is 1 + 2*x^1 + 1*x^2 + 2*x^3
题意:
给你一个长度为m的字符串仅由小写英文字母组成,求满足a1 < ...< ai < ai+1 < Amax > aj > aj+1 > ... > an的子串的个数
思路:
首先它仅包含26个英文字母,我们只要枚举每一个位置,然后记录每个位置左边满足条件的个数,右边满足条件的个数,最后乘起来就是了,那么我们怎么记录左边,右边满足的个数的呢?
dp[c]表示以字符c结尾的满足情况的个数,dl[i]表示第i个位置左边满足条件的个数,dr[i]表示第i个位置右边满足条件的个数,
dp[c] = (dl[i] + 1); s[i] = c; 1表示的s[i]单独一个时满足的情况,dl[i]表示他左边的满足的各种情况+s[i] 后满足情况的。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("data.in", "r", stdin) #define Write() freopen("d.out", "w", stdout) #define M 100007 #define N 100007 using namespace std; const int inf = 0x7f7f7f7f; const int mod = 1000000007; int dp[27],dl[N],dr[N]; int n; char ts[N]; int s[N]; int main() { // Read(); int i,j; while (~scanf("%d",&n)) { scanf("%s",ts); for (i = 0; i < n; ++i) s[i] = ts[i] - 'a'; CL(dp,0); CL(dl,0); CL(dr,0); for (i = 0; i < n; ++i) { for (j = 0; j < s[i]; ++j) dl[i] += dp[j]; dl[i] %= 2012; dp[s[i]] += (dl[i] + 1); dp[s[i]] %= 2012; } CL(dp,0); for (i = n - 1; i >= 0; --i) { for (j = 0; j < s[i]; ++j) dr[i] += dp[j]; dr[i] %= 2012; dp[s[i]] += (dr[i] + 1); dp[s[i]] %= 2012; } int ans = 0; for (i = 0; i < n; ++i) { ans += dl[i]*dr[i]; ans %= 2012; } printf("%d\n",ans); } return 0; }
解法二:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int main() { int t,n,a[60]; int q; __int64 p; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&a[i]); scanf("%d",&q); while(q--) { scanf("%I64d",&p); int loc; int ans=1,cnt=0; while(p) { loc=p&1; // printf("%d",loc); if(cnt>=n) { ans=0; break; } if(loc==1) ans=ans*a[cnt]%2012; cnt++; p>>=1; } printf("%d\n",ans); } } return 0; }
下一题:
Crawling in process... Crawling failed Time Limit:1000MS Memory Limit:131072KB 64bit IO Format:%lld & %llu
Description
Tom is very interested in number problem. Nowadays he is thinking of a problem about A-number and B-number.
A-number is a positive integer whose decimal form contains 7 or it can be divided by 7. We can write down the first 10 A-number ( a[i] is the ith A-number)
{a[1]=7,a[2]=14,a[3]=17,a[4]=21,a[5]=27,a[6]=28,a[7]=35,a[8]=37,a[9]=42,a[10]=47};
B-number is Sub-sequence of A-number which contains all A-number but a[k] ( that k is a A-number.) Like 35, is the 7th A-number and 7 is also an A-number so the 35 ( a[7] ) is not a B-number. We also can write down the first 10 B-number.
{b[1]=7,b[2]=14,b[3]=17,b[4]=21,b[5]=27,b[6]=28,b[7]=37,b[8]=42,b[9]=47,b[10]=49};
Now Given an integer N, please output the Nth B-number.
Input
The input consists of multiple test cases.
For each test case, there will be a positive integer N as the description.
Output
For each test case, output an integer indicating the Nth B-number.
You can assume the result will be no more then 2^63-1.
Sample Input
1
7
100
Sample Output
7
37
470
题意:
给出一个多项式:(a0*x^(2^0)+1) * (a1 * x^(2^1)+1)*.......*(an-1 * x^(2^(n-1))+1)
输入P,求X^p 前边的系数。
思路:
首先P肯定是一个二进制表示的数,并且唯一。我们只要将p转化成二进制数,然后乘上系数就好了。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 137 #define N 55 using namespace std; const int inf = 0x7f7f7f7f; const int mod = 1000000007; int a[N],b[60]; int main() { int T,i; int n,m; scanf("%d",&T); while (T--) { scanf("%d",&n); CL(a,0); for (i = 0; i < n; ++i) scanf("%d",&a[i]); scanf("%d",&m); int top; ll p; while (m--) { cin>>p; top = 0; if (p == 0) { printf("1\n"); continue; } while (p) { b[top++] = p%2; p /= 2; } int ans = 1; for (i = 0; i < top; ++i) { if (b[i]) ans = ans*a[i]%2012; } printf("%d\n",ans); } } return 0; }
最后一题:
Crawling in process... Crawling failed Time Limit:1000MS Memory Limit:131072KB 64bit IO Format:%lld & %llu
Submit Status Practice SDIBT 3239
Description
In ACM/ICPC on-site contests ,3 students share 1 computer,so you can print your source code any time. Here you need to write a contest print server to handle all the requests.
Input
In the first line there is an integer T(T<=10),which indicates the number of test cases.
In each case,the first line contains 5 integers n,s,x,y,mod (1<=n<=100, 1<=s,x,y,mod<=10007), and n lines of requests follow. The request is like "Team_Name request p pages" (p is integer, 0<p<=10007, the length of "Team_Name" is no longer than 20), means the team "Team_Name" need p pages to print, but for some un-know reason the printer will break down when the printed pages counter reached s(s is generated by the function s=(s*x+y)%mod ) and then the counter will become 0. In the same time the last request will be reprint from the very begin if it isn't complete yet(The data guaranteed that every request will be completed in some time).
You can get more from the sample.
Output
Every time a request is completed or the printer is break down,you should output one line like "p pages for Team_Name",p is the number of pages you give the team "Team_Name".
Please note that you should print an empty line after each case
Sample Input
2
3 7 5 6 177
Team1 request 1 pages
Team2 request 5 pages
Team3 request 1 pages
3 4 5 6 177
Team1 request 1 pages
Team2 request 5 pages
Team3 request 1 pages
Sample Output
1 pages for Team1
5 pages for Team2
1 pages for Team3
1 pages for Team1
3 pages for Team2
5 pages for Team2
1 pages for Team3
这道题的题目意思是:打印机的打印方式,如果没有纸了,就记下来,下次再打,没有的时候输出0;
具体见代码,是简单题,
附代码:
#include<stdio.h> int main() { int T; scanf("%d", &T); while(T--) { int n,s,x,y,mod; scanf("%d%d%d%d%d",&n,&s,&x,&y,&mod);//n个队提交的次数,s纸张数, int count,i; count=s; for(i=0;i<n;i++) { char a[50],b[20],c[20]; int num; scanf("%s%s%d%s",a,b,&num,c); while(1) { if(num>count) { printf("%d pages for %s\n",count,a); s=(s*x+y)%mod; if(s==0)//一开始为零 s=(s*x+y)%mod; count=s; } else { printf("%d pages for %s\n",num,a); count=count-num; break; } } } puts(""); } return 0; } /* 2 4 7 5 6 177 Team1 request 1 pages Team2 request 5 pages Team3 request 1 pages Team3 request 8 pages 3 4 5 6 177 Team1 request 1 pages Team2 request 5 pages Team3 request 1 pages */