NOIP模拟赛 6.29

2017-6-29 NOIP模拟赛

Problem 1 机器人(robot.cpp/c/pas)

【题目描述】

早苗入手了最新的Gundam模型。最新款自然有着与以往不同的功能,那就是它能够自动行走,厉害吧。

早苗的新模型可以按照输入的命令进行移动,命令包括‘E’、‘S’、‘W’、‘N’四种,分别对应东南西北。执行某个命令时,它会向对应方向移动一个单位。作为新型机器人,它可以执行命令串。对于输入的命令串,每一秒它会按命令行动一次。执行完命令串的最后一个命令后,会自动从头开始循环。在0时刻时机器人位于(0,0)。求T秒后机器人所在位置坐标。

【输入格式】

1行:一个字符串,表示早苗输入的命令串,保证至少有1个命令

2行:一个正整数T

【输出格式】

2个整数,表示T秒时,机器人的坐标。

【样例输入】

NSWWNSNEEWN

12

【样例输出】

-1 3

【数据范围】

对于60%的数据 T<=500,000 且命令串长度<=5,000

对于100%的数据 T<=2,000,000,000 且命令串长度<=5,000

【注意】

向东移动,坐标改变改变为(X+1,Y);

向南移动,坐标改变改变为(X,Y-1);

向西移动,坐标改变改变为(X-1,Y);

向北移动,坐标改变改变为(X,Y+1);

水过。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring> 
 5 #include <algorithm>
 6 #include <vector>
 7 #include <queue>
 8 inline void read(long long &x){x = 0;char ch = getchar();char c = ch;while(ch > '9' || ch < '0')c = ch, ch = getchar();while(ch >= '0' && ch <= '9')x = x * 10 + ch - '0', ch = getchar();}
 9 inline int max(int a, int b){return a > b ? a : b;}
10 inline int min(int a, int b){return a < b ? a : b;}
11 inline void swap(int &a, int &b){int tmp = a;a = b;b = tmp;}
12 
13 const int INF = 0x3f3f3f3f;
14 const int MAXN = 5000 + 10;
15 
16 char s[MAXN];
17 long long t;
18 long long len, xx, yy;
19 long long x,y;
20 
21 int main()
22 {
23     scanf("%s", s + 1);
24     read(t);
25     len = strlen(s + 1);
26     if(t < len)
27     {
28         for(register int i = 1;i <= t;++ i)
29         {
30             if(s[i] == 'E')++ xx;
31             else if(s[i] == 'S')--yy;
32             else if(s[i] == 'W')--xx;
33             else ++yy;
34         }
35         x = xx;
36         y = yy;
37     }
38     else
39     {
40         for(register int i = 1;i <= len;++ i)
41         {
42             if(s[i] == 'E')++ xx;
43             else if(s[i] == 'S')--yy;
44             else if(s[i] == 'W')--xx;
45             else ++yy;
46         }
47         int group = t / len;
48         x = xx * group;
49         y = yy * group;
50         group = t % len;
51         for(register int i = 1;i <= group;i ++)
52         {
53             if(s[i] == 'E')++ x;
54             else if(s[i] == 'S')--y;
55             else if(s[i] == 'W')--x;
56             else ++y;
57         }
58     }
59     printf("%lld %lld", x, y);
60     return 0;
61 }
View Code

Problem 2 数列(seq.cpp/c/pas)

【题目描述】

a[1]=a[2]=a[3]=1

a[x]=a[x-3]+a[x-1]  (x>3)

a数列的第n项对1000000007(10^9+7)取余的值。

【输入格式】

第一行一个整数T,表示询问个数。 

以下T行,每行一个正整数n。

【输出格式】

每行输出一个非负整数表示答案。

【样例输入】

3

6

8

10

【样例输出】

4

9

19

【数据范围】

对于30%的数据 n<=100;

对于60%的数据 n<=2*10^7;

对于100%的数据 T<=100,n<=2*10^9;

 

矩阵快速幂。

构造矩阵:

1 1 0 0

0 1 0 1

0 1 0 0

0 0 1 0

an

a(n - 2)

a(n - 3)

a(n - 4)

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cstring> 
  5 #include <algorithm>
  6 #include <vector>
  7 #include <queue>
  8 inline void read(long long &x){x = 0;char ch = getchar();char c = ch;while(ch > '9' || ch < '0')c = ch, ch = getchar();while(ch >= '0' && ch <= '9')x = x * 10 + ch - '0', ch = getchar();}
  9 inline int max(int a, int b){return a > b ? a : b;}
 10 inline int min(int a, int b){return a < b ? a : b;}
 11 inline void swap(int &a, int &b){int tmp = a;a = b;b = tmp;}
 12 
 13 const int INF = 0x3f3f3f3f;
 14 const int MOD = 1000000007;
 15 
 16 long long s1[10][10];
 17 long long s2[10];
 18 long long ans[10][10];
 19 long long base[10][10];
 20 long long tmp[10][10];
 21 
 22 long long pow(int b)
 23 {
 24     for(int i = 1;i <= 4;i ++)
 25     {
 26         ans[i][i] = 1;
 27         for(int j = 1;j <= 4;j ++)
 28         {
 29             base[i][j] = s1[i][j] % MOD;
 30         }
 31     }
 32     while(b)
 33     {
 34         
 35         if(b & 1)
 36         {
 37             for(int i = 1;i <= 4;++ i)
 38             {
 39                 for(int j = 1;j <= 4;++ j)
 40                 {
 41                     tmp[i][j] = ans[i][j] % MOD;
 42                 }
 43             }
 44             //    ans *= base;
 45             memset(ans, 0, sizeof(ans));
 46             for(int k = 1;k <= 4;++ k)
 47             {
 48                 for(int i = 1;i <= 4; ++ i)
 49                 {
 50                     for(int j = 1;j <= 4;++ j)
 51                     {
 52                         ans[i][j] += ((tmp[i][k] % MOD) * (base[k][j] % MOD)) % MOD;
 53                     }
 54                 }
 55             }
 56         }
 57         
 58         
 59         for(int i = 1;i <= 4;i ++)
 60         {
 61             for(int j = 1;j <= 4;j ++)
 62             {
 63                 tmp[i][j] = base[i][j] % MOD;
 64             }
 65         }
 66         memset(base, 0, sizeof(base));
 67         for(int k = 1;k <= 4;++ k)
 68         {
 69             for(int i = 1;i <= 4; ++ i)
 70             {
 71                 for(int j = 1;j <= 4;++ j)
 72                 {
 73                     base[i][j] += ((tmp[i][k] % MOD) * (tmp[k][j] % MOD)) % MOD;
 74                 }
 75             }
 76         }
 77         //base = base * base;
 78         b >>= 1;
 79     }
 80     return ((((ans[1][1]%MOD) * (s2[1]%MOD) % MOD) + ((ans[1][2]%MOD) * (s2[2]%MOD) % MOD))%MOD + (((ans[1][3]%MOD) *(s2[3]%MOD)) % MOD + ((ans[1][4]%MOD) * (s2[4]%MOD)) % MOD)%MOD) % MOD;
 81 }
 82 
 83 long long n,t;
 84 
 85 int main()
 86 {
 87     read(t);
 88     while(t)
 89     {
 90         memset(base, 0, sizeof(base));
 91         memset(tmp, 0, sizeof(tmp));
 92         memset(ans, 0, sizeof(ans));
 93         read(n);
 94         if(n == 1 || n == 2 || n == 3)
 95         {
 96             printf("1
");
 97             -- t;
 98             continue;
 99         }
100         else if(n == 4)
101         {
102             printf("2
");
103             -- t;
104             continue;
105         }
106         else if(n == 5)
107         {
108             printf("3
");
109             -- t;
110             continue;
111         }
112         s1[1][1] = 1;s1[1][2] = 1;s1[1][3] = 0;s1[1][4] = 0;
113         s1[2][1] = 0;s1[2][2] = 1;s1[2][3] = 0;s1[2][4] = 1;
114         s1[3][1] = 0;s1[3][2] = 1;s1[3][3] = 0;s1[3][4] = 0;
115         s1[4][1] = 0;s1[4][2] = 0;s1[4][3] = 1;s1[4][4] = 0;
116         s2[1] = 3;s2[2] = 1;s2[3] = 1;s2[4] = 1;
117         long long a = pow(n - 5);
118         printf("%lld
", a % MOD);
119         -- t;
120     } 
121     return 0;
122 }
View Code

Problem 3 虫洞(holes.cpp/c/pas)

【题目描述】

N个虫洞,M条单向跃迁路径。从一个虫洞沿跃迁路径到另一个虫洞需要消耗一定量的燃料和1单位时间。虫洞有白洞和黑洞之分。设一条跃迁路径两端的虫洞质量差为delta。

1.从白洞跃迁到黑洞,消耗的燃料值减少delta,若该条路径消耗的燃料值变为负数的话,取为0。

2.从黑洞跃迁到白洞,消耗的燃料值增加delta。

3.路径两端均为黑洞或白洞,消耗的燃料值不变化。

作为压轴题,自然不会是如此简单的最短路问题,所以每过1单位时间黑洞变为白洞,白洞变为黑洞。在飞行过程中,可以选择在一个虫洞停留1个单位时间,如果当前为白洞,则不消耗燃料,否则消耗s[i]的燃料。现在请你求出从虫洞1到N最少的燃料消耗,保证一定存在1到N的路线。

【输入格式】

1行:2个正整数N,M

2行:N个整数,第i个为0表示虫洞i开始时为白洞,1表示黑洞。

3行:N个整数,第i个数表示虫洞i的质量w[i]。

4行:N个整数,第i个数表示在虫洞i停留消耗的燃料s[i]。

5..M+4行:每行3个整数,u,v,k,表示在没有影响的情况下,从虫洞u到虫洞v需要消耗燃料k。

【输出格式】

一个整数,表示最少的燃料消耗。

【样例输入】

4 5

1 0 1 0

10 10 100 10

5 20 15 10

1 2 30

2 3 40

1 3 20

1 4 200

3 4 200

【样例输出】

130

【数据范围】

对于30%的数据: 1<=N<=100,1<=M<=500

对于60%的数据: 1<=N<=1000,1<=M<=5000

对于100%的数据: 1<=N<=5000,1<=M<=30000

                  其中20%的数据为1<=N<=3000的链

                  1<=u,v<=N, 1<=k,w[i],s[i]<=200

【样例说明】

按照1->3->4的路线。

 

不难发现,无论时间怎样变化,两个点的相对颜色总是不变(即总是同色或异色)

把一个点拆成两个点,分别代表白、黑,记为i,i'

每一s黑白互换,因此当i->j,权值为w时,我们令i->j',权值为w

又由于我们可以在某一个点上停留一个单位时间,从而使得点黑白互换,因此应让i->i'和i'->i连边即可。而又由于任何节点相对颜色不变,我们可以知道走这条边到达i'(i)后仍是合法的。

这样建图跑SPFA即可

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cstring> 
  5 #include <algorithm>
  6 #include <vector>
  7 #include <queue>
  8 inline void read(int &x){x = 0;char ch = getchar();char c = ch;while(ch > '9' || ch < '0')c = ch, ch = getchar();while(ch >= '0' && ch <= '9')x = x * 10 + ch - '0', ch = getchar();}
  9 inline int max(int a, int b){return a > b ? a : b;}
 10 inline int min(int a, int b){return a < b ? a : b;}
 11 inline void swap(int &a, int &b){int tmp = a;a = b;b = tmp;}
 12  
 13 const int INF = 0x3f3f3f3f;
 14 const int MAXN = 1000000;
 15 const int MAXM = 3000000;
 16 
 17 int n,m;
 18 int bw[MAXN << 1],weight[MAXN],s[MAXN];
 19 int tmp1, tmp2, tmp3;
 20 
 21 struct Edge
 22 {
 23     int u,v,next,w;
 24 }edge[MAXM];
 25 int head[MAXN << 1],cnt;
 26 void insert(int a, int b, int c){edge[++cnt] = Edge{a, b, head[a], c};head[a] = cnt;}
 27 
 28 std::queue<int> q;
 29 int b[MAXN << 1],d[MAXN];
 30 
 31 void SPFA()
 32 {
 33     memset(d, 0x3f, sizeof(d));
 34     q.push(2);d[2] = 0;
 35     b[2] = true;
 36     register int u,v;
 37     while (!q.empty())
 38     {
 39         u = q.front();
 40         q.pop();
 41         b[u] = false;
 42         for (int pos = head[u];pos;pos = edge[pos].next)
 43         {
 44             v = edge[pos].v;
 45             if (d[v] > d[u] + edge[pos].w)
 46             {
 47                 d[v] = d[u] + edge[pos].w;
 48                 if (!b[v])
 49                 {
 50                     b[v] = true;
 51                     q.push(v);
 52                 }
 53             }
 54         }
 55     }
 56 }
 57 
 58 int main()
 59 {
 60     read(n);read(m);
 61     
 62     for (register int i = 1;i <= n;++ i)
 63     {
 64         read(bw[i << 1]);
 65         bw[i << 1 | 1] = 1 ^ bw[i << 1];
 66     }
 67     
 68     for (register int i = 1;i <= n;++ i)
 69     {
 70         read(weight[i]);
 71     }
 72     
 73     for (register int i = 1;i <= n;++ i)
 74     {
 75         read(s[i]);
 76         int w = s[i];
 77         if (!bw[i << 1])
 78             insert(i << 1, i << 1 | 1, 0),insert(i << 1 | 1, i << 1, s[i]); 
 79         else 
 80             insert(i << 1, i << 1 | 1, s[i]),insert(i << 1 | 1, i << 1, 0); 
 81     }
 82     
 83     for (register int i = 1;i <= m;++ i)
 84     {
 85         read(tmp1);read(tmp2);read(tmp3);
 86         int w1 = 0,w2 = 0;
 87         
 88         //0 白  1  黑
 89         
 90         //相同 不变化 
 91         
 92         if (bw[tmp1 << 1] == bw[tmp2 << 1])
 93             w1 = w2 = tmp3;
 94             
 95         //0 -> 1  减小weight差 ,负数记为0
 96         
 97         if (bw[tmp1 << 1] == 0 && bw[tmp2 << 1] == 1)
 98             w1 = tmp3 - abs(weight[tmp1] - weight[tmp2]);
 99         if (bw[tmp1 << 1 | 1] == 0 && bw[tmp2 << 1 | 1] == 1)
100             w2 = tmp3 - abs(weight[tmp1] - weight[tmp2]);
101             
102         //1 -> 0 增加weight差
103         
104         if (bw[tmp1 << 1] == 1 && bw[tmp2 << 1] == 0)
105             w1 = tmp3 + abs(weight[tmp1] - weight[tmp2]);
106         if (bw[tmp1 << 1 | 1] == 1 && bw[tmp2 << 1 | 1] == 0)
107             w2 = tmp3 + abs(weight[tmp1] - weight[tmp2]);
108             
109         if (w1 < 0)
110             w1 = 0;
111         if (w2 < 0)
112             w2 = 0;
113             
114         insert(tmp1 << 1, tmp2 << 1 | 1, w1);
115         insert(tmp1 << 1 | 1, tmp2 << 1, w2);
116     }
117     
118     SPFA();
119     
120     printf("%d", min(d[n << 1], d[n << 1 | 1]));
121     return 0;
122 }
View Code

第一次AK,开森~

题怪简单

原文地址:https://www.cnblogs.com/huibixiaoxing/p/7093198.html