2013山东省ICPC结题报告

A、Rescue The Princess

 1 #include <cstdio>
2 #include <cmath>
3 #include <iostream>
4
5 using namespace std;
6
7 const double pi = acos(-1.0);
8 double xx1,yy1,xx2,yy2,xx3,yy3,jiao,leng;
9
10 int main(int argc, char const *argv[])
11 {
12     freopen("SD_3230_Rescue_The_Princess.in","r",stdin);
13     int amount;
14     scanf("%d",&amount);
15     while(amount--){
16         scanf("%lf %lf %lf %lf",&xx1,&yy1,&xx2,&yy2);
17         jiao = atan2(yy2-yy1,xx2-xx1);
18         leng = sqrt(pow(xx1-xx2,2)+pow(yy1-yy2,2));
19         xx3 = xx1 + leng*cos(jiao+pi/3.0);
20         yy3 = yy1 + leng*sin(jiao+pi/3.0);
21         printf("(%.2lf,%.2lf)\n", xx3,yy3);
22     }
23     return 0;
24 }
View Code

B、Thrall’s Dream

给出N个点N (0 <= N < 2001)，M条边M (0 <= M < 10001)构成的图，判断是否任意两点可达，可达输出“Kalimdor is just ahead“，否则输出”The Burning Shadow consume us all“。

  1 #include <cstdio>
2 #include <iostream>
3 #include <cstring>
4 #include <stack>
5
6 #ifndef SYMBOL
7 #define MAXN 2001
8 #endif
9
10 using namespace std;
11 /*
12 dfs变形的targan算法，求强连通图的强联通分量
13 */
14
15 struct node
16 {
17     int size;
18     int indegree;
20     int instack;
21     int father;
22 };
23
24 int childs[MAXN][MAXN],low[MAXN],dfn[MAXN];
25 int nodeAmount,edgeAmount,times,mins,outzero;
26 stack<int> stacks;
27 struct node nodes[MAXN];
28
29 void init(){
30     for (int i = 1;i <= MAXN;i ++){
31         nodes[i].size = 0;
33         nodes[i].instack = 0;
34         nodes[i].indegree = 0;
35     }
36     times = 0;
37     outzero = 0;
38     mins = 0;
39     memset(childs,0,sizeof(childs));
40     memset(low,0,sizeof(low));
41     memset(dfn,0,sizeof(dfn));
42     memset(nodes,0,sizeof(nodes));
43     while(!stacks.empty()){
44         stacks.pop();
45     }
46 }
47
48 void targan(int n){
49     times ++;
50     dfn[n] = times;
51     low[n] = times;
52     stacks.push(n);
54     nodes[n].instack = 1;
55     int child;
56     mins = dfn[n];
57     for (int i = 0;i < nodes[n].size;i ++){
58         child = childs[n][i];
59         nodes[child].father = n;
60         if (nodes[child].instack){
61             mins = std::min(mins ,dfn[child]);
62             mins = std::min(mins ,low[child]);
63             low[n] = mins;
64         }
66             targan(child);
67         }
68     }
69     int father = nodes[n].father;
70     mins = low[father];
71     mins = std::min(mins ,dfn[n]);
72     mins = std::min(mins ,low[n]);
73     low[father] = mins;
74     if (dfn[n] == low[n]){
75         int nod;
76         bool isout = false;
77         while(1){
78             nod = stacks.top();
79             stacks.pop();
80             nodes[nod].instack = 0;
81             int size = nodes[nod].size;
82             int chil;
83             for (int k = 0;k < size;k ++){
84                 chil = childs[nod][k];
85                 if (low[chil] != low[nod]){
86                     isout = true;
87                 }
88             }
89             if (nod == n) break;
90         }
91         if (!isout){
92             outzero ++;
93         }
94     }
95 }
96
97 bool judge(){
98     if (outzero >= 2){
99         return false;
100     }
101     return true;
102 }
103
104 int main(){
105     freopen("SD_3231_Thralls_Dream.in","r",stdin);
106     int amount;
107     scanf("%d",&amount);
108     for (int i = 1;i <= amount;i ++){
109         scanf("%d %d",&nodeAmount,&edgeAmount);
110         init();
111         int from,to;
112         for (int j = 0;j < edgeAmount;j ++){
113             scanf("%d %d",&from,&to);
114             int size = nodes[from].size;
115             childs[from][size++] = to;
116             nodes[from].size = size;
117             nodes[to].indegree ++;
118         }
119         for (int k = 1;k <= nodeAmount;k ++){
121                 targan(k);
122             }
123         }
124         if (judge()) {
125             printf("Case %d: Kalimdor is just ahead\n", i);
126         } else {
127             printf("Case %d: The Burning Shadow consume us all\n",i);
128         }
129     }
130     return 0;
131 }
View Code

C、A^X mod P

f(x) = K, x = 1，f(x) = (a*f(x-1) + b)%m , x > 1，求( A^(f(1)) + A^(f(2)) + A^(f(3)) + ...... + A^(f(n)) ) modular P. 1 <= n <= 10^6，0 <= A, K, a, b <= 10^9，1 <= m, P <= 10^9

10^9无论从空间还是时间上都是不可行的，所以简单的计算绝对不行，A^(10^9)我们可以预处理一下，求A^(ki+j)直接将10^9的复杂度降了一个平方。只需求出A^k即可

 1 #include <cstdio>
2 #include <cmath>
3 #include <iostream>
4
5 #ifndef SYMBOL
6 #define MAXK 100005
7 #endif
8
9 typedef long long ll;
10
11 using namespace std;
12 /*
13 合理的运用%的特性
14 预处理(A^1~n)%P次方
15 */
16
17 ll n, A, K, a, b, m, P;
18 ll pre1[MAXK+1],pre2[MAXK+1];
19
20 void init(){
21     pre1[0] = pre2[0] = 1LL;
22     for (int i = 1;i <= MAXK;i ++){
23         pre1[i] = A*pre1[i-1]%P;
24     }
25     for (int i = 1;i <= MAXK;i ++){
26         pre2[i] = pre2[i-1]*pre1[MAXK]%P;
27     }
28 }
29
30 ll gao(){
31     ll res = 0,t = K;
32     for (int i = 1;i <= n;i ++){
33         res = (res + pre2[t/MAXK]*pre1[t%MAXK])%P;
34         t = (a*t + b)%m;
35     }
36     return res;
37 }
38
39 int main(int argc, char const *argv[])
40 {
41     freopen("SD_3232_AX_mod_P.in","r",stdin);
42     int test;
43     scanf("%d",&test);
44     for (int i = 1;i <= test;i ++){
45         scanf("%lld %lld %lld %lld %lld %lld %lld",&n,&A,&K,&a,&b,&m,&P);
46         init();
47         printf("Case #%d: %lld\n", i,gao());
48     }
49     return 0;
50 }
View Code

D、Rubik’s cube

  1 #include <cstdio>
2 #include <iostream>
3 #include <algorithm>
4 #include <queue>
5 #include <map>
6
7 #ifndef SYMBOL
8 #define CUBE 24
9 #define ONLINE_JUDGE 1
10 #endif
11
12 using namespace std;
13
14 struct node
15 {
16     int cu[CUBE];
17     int step;
18 };
19
20 node start;
21 queue<node> que;
22 map<int,int> myhash;
23 int rode[6][8] = {
24     {4,6,17,16,15,13,9,8},
25     {1,3,2,0},
26     {1,3,17,19,22,20,10,8},
27     {4,6,7,5},
28     {0,1,4,5,20,21,12,13},
29     {9,8,10,11}
30 };
31
32 void turn(node & n,int face){
33     face<<=1;
34     int t = n.cu[rode[face][0]];
35     for (int i = 0;i < 7;i ++){
36         n.cu[rode[face][i]] = n.cu[rode[face][i+1]];
37     }
38     n.cu[rode[face][7]] = t;
39     t = n.cu[rode[face][0]];
40     for (int i = 0;i < 7;i ++){
41         n.cu[rode[face][i]] = n.cu[rode[face][i+1]];
42     }
43     n.cu[rode[face][7]] = t;
44     face ++;
45     t = n.cu[rode[face][0]];
46     for (int i = 0;i < 3;i ++){
47         n.cu[rode[face][i]] = n.cu[rode[face][i+1]];
48     }
49     n.cu[rode[face][3]] = t;
50 }
51
52 int myhashCode(const node n){
53     int res = 0;
54     for (int i = 0;i < 24;i ++){
55         res = n.cu[i] + (res<<1);
56     }
57     return res;
58 }
59
60 bool isOK(const node n){
61     for (int i = 0;i < 24;i += 4){
62         for (int j = 1;j <= 3;j ++){
63             if (n.cu[i] != n.cu[i+j]){
64                 return false;
65             }
66         }
67     }
68     return true;
69 }
70
71 int bfs(){
72     int red = 0;
73     for (int i = 0;i < 24;i ++){
74         if (start.cu[i] == 0){
75             red ++;
76         }
77     }
78     if (red%4 != 0){
79         return -1;
80     }
81     if (isOK(start)){
82         return start.step;
83     }
84     myhash.clear();
85     while(!que.empty()) que.pop();
86     myhash[myhashCode(start)] = 1;
87     que.push(start);
88     node s,t;
89     while(!que.empty()){
90         s = que.front();
91         que.pop();
92         for (int i = 0;i < 3;i ++){
93             t = s;
94             t.step ++;
95             turn(t,i);
96             if (myhash.find(myhashCode(t)) == myhash.end()){
97                 if (isOK(t)){
98                     return t.step;
99                 }
100                 myhash[myhashCode(t)] = 1;
101                 que.push(t);
102             }
103             turn(t,i);
104             turn(t,i);
105             if (myhash.find(myhashCode(t)) == myhash.end()){
106                 if (isOK(t)){
107                     return t.step;
108                 }
109                 myhash[myhashCode(t)] = 1;
110                 que.push(t);
111             }
112         }
113     }
114     return -1;
115 }
116
117 int main(int argc, char const *argv[])
118 {
119     #ifndef ONLINE_JUDGE
120     freopen("SD_3232_Rubiks_cube.in","r",stdin);
121     #endif
122     int test;
123     scanf("%d",&test);
124     while(test--){
125         for (int i = 0;i < 24;i ++){
126             scanf("%d",&start.cu[i]);
127         }
128         start.step = 0;
129         int res = bfs();
130         if (res == -1) printf("IMPOSSIBLE!\n");
131         else printf("%d\n", res);
132     }
133     return 0;
134 }
View Code

E、Mountain Subsequences

 1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #define MAX 100000
5 #define MOD 2012
6 using namespace std;
7 //cnt记录单个字符的个数，dp记录以此字母结束的个数
8 int leng,up[MAX],down[MAX],dp[26],cnt[26],t;
9 char str[MAX];
10 int main() {
11     freopen("SD_3234_Mountain_Subsequences.in","r",stdin);
12     while(~scanf("%d",&leng)){
13         scanf("%s",str);
14         memset(up,0,sizeof(up));
15         memset(down,0,sizeof(down));
16         memset(dp,0,sizeof(dp));
17         memset(cnt,0,sizeof(cnt));
18         for (int i = 0;i < leng;i ++){
19             t = str[i] - 'a';
20             for (int j = 0;j < t;j ++){
21                 up[i] += dp[j] + cnt[j];
22                 up[i] %= MOD;
23             }
24             cnt[t] ++;
25             cnt[t] %= MOD;
26             dp[t] += up[i];
27             dp[t] %= MOD;
28         }
29         memset(dp,0,sizeof(dp));
30         memset(cnt,0,sizeof(cnt));
31         for (int i = leng-1;i >= 0;i --){
32             t = str[i] - 'a';
33             for (int j = 0;j < t;j ++){
34                 down[i] += dp[j] + cnt[j];
35                 down[i] %= MOD;
36             }
37             cnt[t] ++;
38             cnt[t] %= MOD;
39             dp[t] += down[i];
40             dp[t] %= MOD;
41         }
42         int sum = 0;
43         for (int i = 1;i < leng-1;i ++){
44             sum += up[i]*down[i];
45             sum %= MOD;
46         }
47         printf("%d\n", sum);
48     }
49     return 0;
50 }
View Code

F、Alice and Bob

(a0*x^(2^0)+1) * (a1 * x^(2^1)+1)*.......*(an-1 * x^(2^(n-1))+1)，求x^P的系数

1 <= P <= 2^0+2^1+2^2+.....+2^(n-1)，二次项有个性质2^0+2^1+......+2^(n-1)<2^n，所以可以推断出P只能由唯一的二次项系数构成。将P的二进制求出来，将其中值为1的项的系数相乘即为结果。

 1 #include <cstdio>
2 #include <iostream>
3 #include <cmath>
4 #include <cstring>
5
6 #ifndef SYMBOL
7 #define MAX 55
8 #endif
9
10 using namespace std;
11 /*
12 定理：一个数只能由2的多项式中唯一的序列构成2^0 2^1 2^2 2^3 2^4 ,7只能由2^0 2^1 2^2构成
13 */
14
15 typedef long long ll;
16
17 int n,dex;
18 int co[MAX],binary[MAX];
19
20 void getBinary(ll number){
21     memset(binary,0,sizeof(binary));
22     dex = 0;
23     while(number){
24         binary[dex++] = number%2LL;
25         number /= 2LL;
26     }
27 }
28
29 int calcu(ll P){
30     if (P == 0LL){
31         return 1;//一定要考虑极限问题
32     }
33     ll max = 0;
34     for (int i = 0;i < n;i ++){
35         max += pow(2LL,i);
36     }
37     if (P > max){
38         return 0;//一定要考虑极限问题
39     }
40     getBinary(P);
41     int sum = 1;
42     for (int i = 0;i < dex;i ++){
43         if (binary[i]){
44             sum *= co[i];
45             sum %= 2012;
46         }
47     }
48     return sum;
49 }
50
51 int main(int argc, char const *argv[])
52 {
53     // freopen("SD_3235_Alice_and_Bob.in","r",stdin);
54     // freopen("SD_3235_Alice_and_Bob.out","w",stdout);
55     int test,ques;
56     ll P;
57     scanf("%d",&test);
58     while(test--){
59         scanf("%d",&n);
60         for (int i = 0;i < n;i ++){
61             scanf("%d",&co[i]);
62         }
63         scanf("%d",&ques);
64         while(ques--){
65             scanf("%lld",&P);
66             printf("%d\n",calcu(P));
67         }
68     }
69     return 0;
70 }
View Code

G、A-Number and B-Number

 1 #include <cstdio>
2 #include <cstring>
3 #include <iostream>
4
5 #ifndef SYMBOL
6 #define MAX 25
7 #endif
8
9 /*
10 位数动态规划,设定最大25位,dp的方式有很多
11 */
12 using namespace std;
13
14 typedef unsigned long long ull;
15
16 ull number;
17 ull dp[MAX][7][2];
18 int bits[MAX];
19
20 ull dfs(int d,int mod7,int have7,bool limit){
21     if (!d){
22         return (!mod7 || have7);
23     }
24     if (!limit && ~dp[d][mod7][have7]){
25         return dp[d][mod7][have7];
26     }
27     int mn = 9;
28     if (limit){
29         mn = bits[d];
30     }
31     ull sum = 0ULL;
32     for (int i = 0;i <= mn;i ++){
33         int tmod7 = (10*mod7+i)%7;
34         int thave7 = have7 || (i == 7);
35         sum += dfs(d-1,tmod7,thave7,(i == mn) && limit);
36     }
37     if (!limit){
38         dp[d][mod7][have7] = sum;
39     }
40     return sum;
41 }
42
43 ull AAmount(ull n){
44     int dex = 0;
45     while(n){
46         bits[++dex] = n%10;
47         n/=10;
48     }
49     return dfs(dex,0,0,true)-1;
50 }
51
52 ull twoSplite(){
53     ull l = 7ULL,r = (1ULL<<63) - 1,m;
54     while(l <= r){
55         m = (l+r)>>1;
56         ull amount = AAmount(m);
57         amount = amount - AAmount(amount);
58         if (amount < number){
59             l = m+1;
60         }else {
61             r = m-1;
62         }
63         //注意这里==不能返回
64     }
65     return l;
66 }
67
68 int main(int argc, char const *argv[])
69 {
70     freopen("SD_3236_A-Number_and_B-Number.in","r",stdin);
71     memset(dp,-1,sizeof(dp));
72     while(~scanf("%llu",&number)){
73         printf("%llu\n", twoSplite());
74     }
75     return 0;
76 }
View Code

H、Boring Counting

  1 #include <cstdio>
2 #include <iostream>
3 #include <algorithm>
4
5 #ifndef SYMBOL
6 #define MAX 50005
7 #endif
8
9 /*无形的线段树*/
10 using namespace std;
11
12 struct num
13 {
14     int value;
15     int dex;
16     bool operator <(const num n) const {return value < n.value;};
17 }nums[MAX];
18
19 struct query
20 {
21     int l;
22     int r;
23     int a;
24     int b;
25     int dex;
26 }querys[MAX];
27
28 bool comp1(const query q1,const query q2) {
29     return q1.a < q2.a;
30 }
31
32 bool comp2(const query q1,const query q2) {
33     return q1.b < q2.b;
34 }
35
36 int nn,qn;
37 int minsum[MAX<<2],ans[MAX][2];
38 /*ans[MAX][0]记录比a小数的个数，ans[MAX][1]记录比b小数的个数，答案为ans[MAX][1]-ans[MAX][0]*/
39
40 /*创建线段树,额外添加的问题值为在这个范围内的个数*/
41 void build(int l,int r,int dex){
42     if (l == r){
43         minsum[dex] = 0;
44         return ;
45     }
46     int m = (l+r)>>1;
47     build(l,m,dex<<1);
48     build(m+1,r,dex<<1|1);
49     minsum[dex] = minsum[dex<<1] + minsum[dex<<1|1];
50 }
51
52 void update(int d,int l,int r,int dex){
53     if (l == r){
54         minsum[dex] ++;
55         return ;
56     }
57     int m = (l+r)>>1;
58     if (d <= m){
59         update(d,l,m,dex<<1);
60     }else{
61         update(d,m+1,r,dex<<1|1);
62     }
63     minsum[dex] = minsum[dex<<1] + minsum[dex<<1|1];
64 }
65
66 int queryy(int ql,int qr,int l,int r,int dex){
67     if (ql <= l && qr >= r){
68         return minsum[dex];
69     }
70     int m = (l+r)>>1;
71     int res = 0;
72     if (ql <= m){
73         res += queryy(ql,qr,l,m,dex<<1);
74     }
75     if (qr > m){
76         res += queryy(ql,qr,m+1,r,dex<<1|1);
77     }
78     return res;
79 }
80
81 void calculate(){
82     build(1,nn,1);
83     sort(nums+1,nums+nn+1);
84     sort(querys+1,querys+qn+1,comp1);
85     int dd = 1;
86     for (int j = 1;j <= qn;j ++){
87         while(dd <= nn && nums[dd].value < querys[j].a){//注意这里等于不能包括在内
88             update(nums[dd].dex,1,nn,1);
89             dd++;
90         }
91         ans[querys[j].dex][0] = queryy(querys[j].l,querys[j].r,1,nn,1);
92     }
93     build(1,nn,1);
94     sort(querys+1,querys+qn+1,comp2);
95     dd = 1;
96     for (int j = 1;j <= qn;j ++){
97         while(dd <= nn && nums[dd].value <= querys[j].b){
98             update(nums[dd].dex,1,nn,1);
99             dd++;
100         }
101         ans[querys[j].dex][1] = queryy(querys[j].l,querys[j].r,1,nn,1);
102     }
103 }
104
105 void print(int cases){
106     printf("Case #%d:\n",cases);
107     for (int i = 1;i <= qn;i ++){
108         printf("%d\n",ans[i][1]-ans[i][0]);
109     }
110 }
111
112 int main(int argc, char const *argv[])
113 {
114     freopen("SD_3237_Boring_Counting.in","r",stdin);
115     int test;
116     scanf("%d",&test);
117     for (int i = 1;i <= test;i ++){
118         scanf("%d %d",&nn,&qn);
119         for (int j = 1;j <= nn;j ++){
120             scanf("%d",&nums[j].value);
121             nums[j].dex = j;
122         }
123         for (int j = 1;j <= qn;j ++){
124             scanf("%d %d %d %d",&querys[j].l,&querys[j].r,&querys[j].a,&querys[j].b);
125             querys[j].dex = j;
126         }
127         calculate();
128         print(i);
129     }
130     return 0;
131 }
View Code

I、The number of steps

 1 #include <cstdio>
2 #include <iostream>
3
4 #define maxn 55
5
6 using namespace std;
7
8 double dp[maxn][maxn];
9
10 int main()
11 {
12     // freopen("SD_3238_The_number_of_steps.in","r",stdin);
13     int n;
14     while(scanf("%d",&n),n)
15     {
16         double a,b,c,d,e;
17         scanf("%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e);
18         dp[n][0]=0;
19         for(int i=1;i<=n;++i)
20             dp[n][i]=dp[n][i-1]+1.0;
21         for(int i=n-1;i>0;--i)
22         {
23             dp[i][0]=a*dp[i+1][0]+b*dp[i+1][1]+1.0;
24             for(int j=1;j<n;++j)
25                 dp[i][j]=c*dp[i+1][j]+d*dp[i+1][j+1]+e*dp[i][j-1]+1.0;
26         }
27         printf("%.2lf\n",dp[1][0]);
28     }
29     return 0;
30 }
View Code

J、Contest Print Server

 1 #include <cstdio>
2 #include <iostream>
3
4 #ifndef SYMBOL
5 #define MAX 100
6 #endif
7
8 using namespace std;
9
11 {
12     char name[30];
13     int page;
15
16 int n,s,x,y,mod;
17
18
19 void print(){
20     int task = 0, sum = 0;
22         if (sum == s){
24             s=(s*x+y)%mod;
25             sum = 0;
30         }else{
32             sum = 0;
33             s=(s*x+y)%mod;
34         }
35     }
36 }
37
38 int main(int argc, char const *argv[])
39 {
40     // freopen("SD_3239_Contest Print_Server.in","r",stdin);
41     // freopen("SD_3239_Contest Print_Server.out","w",stdout);
42     int test;
43     scanf("%d",&test);
44     while(test--){
45         scanf("%d %d %d %d %d",&n,&s,&x,&y,&mod);
46         for (int i = 0;i < n;i ++){
53 }