jxnu acm新生选拔赛

最小的数

Problem Description

定义一种正整数集合K,集合中有N个数,集合中元素Ki(1<=i<=N)是包含i个不同质因子的最小的数。因为Ki可能会很大,所以将集合中所有Ki对10^9+7取余。

Input

本题只有唯一一组测试数据,第一行给出N,q,表示K的个数以及q次询问。1<=N<=1000,q<=10^5.
接下来q行每行一个正整数(64位整数范围内),请判断其对10^9+7取余后,是否在集合K中。

Output

对于每次询问,根据题意输出Yes或No

Sample Input

3 3
2
6
33

Sample Output

Yes
Yes
No

直接用set保存下,查询就从set里查询就行。
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 #include <set>
 6 #define ll long long
 7 using namespace std;
 8 const int MAX = 1e4+10;
 9 const int MOD = 1e9+7;
10 int vis[10010],b[MAX*10],k;
11 void init() {
12     for(int i = 2; i < 10000; i ++) {
13         if(!vis[i]){
14             b[++k] = i;
15             for(int j = i+i; j < 10000; j += i)
16                 vis[j] = 1;
17         }
18     }
19 }
20 int main() {
21     int n,q;
22     std::ios::sync_with_stdio(false);
23     init();
24     cin>>n>>q;
25     set<ll> st;
26     for(int i = 1; i <= n; i ++) {
27         ll ans = 1;
28         for(int j = 1; j <= i; j ++) {
29             ans = 1LL*b[j]*ans%MOD;
30         }
31         st.insert(ans);
32     }
33     ll num;
34     while(q--) {
35         cin>>num;
36         if(st.count(num)) printf("Yes\n");
37         else printf("No\n");
38     }
39     return 0;
40 }

 

不安全字符串


Problem Description

集训十分无聊,于是boss发明了一个“益智”游戏——假设有一段仅由U和L构成的字符串,我们定义当连续的U的个数大于等于三的时候,这个字符串是不安全的。现告诉你字符串的长度n,请你算出能够生成多少个不安全字符串。

Input

输入有多组,每组仅输入一个n,代表字符串的长度,当n等于0的时候输入结束。(4<=n<=30)

Output

输出可生成的不安全字符串的个数。

Sample Input

4
5
0

Sample Output

3
8

Hint:对于第一个样例,当n为4的时候,我们满足条件的有 UUUU LUUU UUUL 三种情况

思路:递推吧,因为每一个情况都是由前一个情况转变过来的,所以用一个dp数组去存每个情况相应的值,每一层的意思如下:(i为当前序列的长度)

dp[i][0]没有三个连续U的序列最右边为L
dp[i][1]没有三个连续U的序列最右边有一个U
dp[i][2]没有三个连续U的序列最右边有两个连续的U
dp[i][3]有三个连续的U的序列

结合每个情况可以发现

    1. dp[i][0]可以由dp[i-1][0]+dp[i-1][1]+dp[i-1][2]转变过来,因为前一状态只要不是有了3个连续的U的序列,在最右边加一个L就可以形成
    2. dp[i][1]可以由dp[i - 1][0]转变过来,因为只能是在最右边没有U的序列加上个U形成
    3. dp[i][2]可以由dp[i - 1][1]转变过来,因为只能是在最右边有一个U的序列加上个U形成
    4. dp[i][3]可以由dp[i - 1][3] * 2 + dp[i - 1][2]转变过来,因为如果原本就是有连续3个U的序列最右边加上什么都是该情况,然后也可以在最右边有两个U的序列加上个U形成

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #define ll long long
 5 using namespace std;
 6 ll dp[33][4];
 7 int main() {
 8     dp[1][0] = dp[1][1] = 1;
 9     dp[1][2] = dp[1][3] = 0;
10     for(int i = 2; i < 33; i ++) {
11         dp[i][0] = dp[i-1][0] + dp[i-1][1] + dp[i-1][2];
12         dp[i][1] = dp[i-1][0];
13         dp[i][2] = dp[i-1][1];
14         dp[i][3] = dp[i-1][3]*2 + dp[i-1][2];
15     }
16     int n;
17     while(scanf("%d",&n)&&n) {
18         cout << dp[n][3] << endl;
19     }
20     return 0;
21 }

 

 

壮壮的数组


Problem Description

A,B,C为三个元素个数为n的数组,A={a1,a2,a3...an},B={b1,b2,b3...bn},C={c1,c2,c3...cn};
已知A、B数组,而且有ci等于ai或bi(1<=i<=n),毫无疑问,C数组有很多种组合。
但是zz不希望C数组全由A数组或者B数组组成,每一种组合都有一个K值,K=c1*c2*c3*...*cn。
现在需要你求出每一种组合对应的K值,并将它们加起来的结果。这个结果可能会很大,请将答案对1e9+7取模。
例如A={1,2,3} B={2,2,4}。
C数组可能为{a1,b2,b3} {b1,a2,b3} {b1,b2,a3} {a1,a2,b3} {a1,b2,a3} {b1,a2,a3}
K值分别为8,16,12,8,6,12,所以你应该输出62。

大量输入,建议使用scanf

Input

输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(1<=n<=100000),表示A,B,C数组元素个数,第二行有n个数据表示a1 a2 a3...an,第三行有n个数据表示b1 b2 b3...bn,(1<=ai,bi<=1e9)。处理到文件的结束。

Output

对于每个测试实例,输出一行数据表示问题的答案,请将答案对1e9+7取模。

Sample Input

3
1 2 3
2 2 4
1
3
4

Sample Output

62
0


其实就是求(a1+b1)*(a2+b2)*....*(an+bn)-a1*a2...*an-b1*b2*...*bn。答案取摸就行。
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #define ll long long
 5 using namespace std;
 6 const int MAX = 100010;
 7 const int mod = 1e9+7;
 8 ll a[MAX], b[MAX];
 9 int main() {
10     int n;
11     std::ios::sync_with_stdio(false);
12     while(cin>>n) {
13         ll ans = 1;
14         for(int i = 1; i <= n; i ++) {
15             cin >> a[i];
16             ans *= a[i];
17             ans %= mod;
18         }
19         ll cnt = 1;
20         for(int i = 1; i <= n; i ++) {
21             cin >> b[i];
22             cnt *= b[i];
23             cnt %= mod;
24         }
25         ll sum = 1;
26         for(int i = 1; i <= n; i ++) {
27             sum *= (a[i]+b[i]);
28             sum %= mod;
29         }
30         cout << (sum+mod-ans+mod-cnt)%mod << endl;
31     }
32     return 0;
33 }

 

 

 

涛涛的Party

Problem Description

涛神因为极强,并且特别帅,所以拥有很多美女的联系方式,每个美女都有自己的食量以及魅力值,大家都知道,物以类聚,人以群分,朋友的朋友就是自己的朋友,所以美女一般都是有自己的美女朋友圈,而且这些美女特别团结,如果她的朋友有没有被邀请的她就不会答应邀请。涛涛想办一个party,但是他只准备了w kg的食物,他想获得最大的美女魅力值,不知道怎么邀请美女,于是他去问你,你能告诉他,他能获得的美女魅力数是多少吗

Input

数据有多组,第一行输入n,m和w(1≤n≤1000,0≤m≤min(n*(n-1)/2,10^5),1≤w≤1000);第二行输入n个整型变量w1,w2,...,wn(1≤wi≤1000)代表美女i的食量;第三行输入n个整型变量b1,b2,...,bn(1≤bi≤106)代表美女i的魅力值;接下来的m行输入两个数x和y(1≤xi,yi≤n,xi≠yi),代表x和y是朋友

Output

输出涛涛能获得的最大魅力值

Sample Input

3 1 5
3 2 5
2 4 2
1 2
4 2 11
2 4 6 6
6 4 2 1
1 2
2 3

Sample Output

6
1

并查集和01背包的运用,同一个集合下的人可以当成一个人。
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 #include <set>
 6 using namespace std;
 7 int n,m,W;
 8 int w[1010], b[1010],fa[1010], dp[1010];
 9 struct Nod{
10     int w, b;
11     Nod(){
12         w = b = 0;
13     }
14 }nod[1010];
15 int find(int x) {
16     return fa[x] = (x==fa[x])?x:find(fa[x]);
17 }
18 void unite(int x, int y) {
19     x = find(x);
20     y = find(y);
21     if(x < y) fa[y] = x;
22     else fa[x] = y;
23 }
24 int main() {
25     std::ios::sync_with_stdio(false);
26     while(cin>>n>>m>>W) {
27         for(int i = 1; i <= n; i ++) cin>>w[i],fa[i] = i;
28         for(int i = 1; i <= n; i ++) cin>>b[i];
29         for(int i = 1; i <= m; i ++) {
30             int x, y;
31             cin>>x>>y;
32             unite(x,y);
33         }
34         for(int i = 1; i <= n; i ++) {
35             int x = find(i);
36             nod[x].w += w[i];
37             nod[x].b += b[i];
38         }
39         for(int i = 1; i <= n; i ++) {
40             if(nod[i].b != 0 && nod[i].w != 0) {
41                 for(int j = W; j >= nod[i].w; j --) {
42                     dp[j] = max(dp[j],dp[j-nod[i].w]+nod[i].b);
43                 }
44             }
45         }
46         printf("%d\n",dp[W]);
47         for(int i = 1; i <= n; i ++){
48             nod[i].b = nod[i].w = 0;
49         }
50         memset(dp,0,sizeof(dp));
51     }
52     return 0;
53 }

手机信号

Problem Description

现在在市面上流传了一款功能极简的手机,在手机上用一个 7×7 的显示屏来显示手机信号,每个区块能显示一个字符。满信号的时候显示如下:

+-----+
|- 4G|
|-- |
|--- |
|---- |
|-----|
+-----+
(杭电描述区块对字宽的设定不统一,正确显示请看输出样例)
每一格信号(第i(1≤i≤5) 格信号有 i个-)代表 20% 的信号强度,不足一格信号的部分不显示。同时会在右上角显示当前的网络传输模式。在信号强度不低于 90% 的时候显示4G;当信号低于 90%、不低于 60% 的时候显示3G;否则显示E。
对于给定的当前信号强度 d%,输出信号的 7×7 像素的图案。

Input

输入一个整数 d(0≤d≤100),表示信号强度。

Output

按照题目要求输出,每行末尾不要输出多余的空白字符。

Sample Input

0
65

Sample Output

+-----+
|    E|
|     |
|     |
|     |
|     |
+-----+
+-----+
|-  3G|
|--   |
|---  |
|     |
|     |
+-----+

直接判断下就行了。
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int main(){
 4     int d;
 5     while(cin>>d){
 6         if(d < 20){
 7             cout << "+-----+\n|    E|\n|     |\n|     |\n|     |\n|     |\n+-----+\n";
 8         }else if(d < 40){
 9             cout << "+-----+\n|-   E|\n|     |\n|     |\n|     |\n|     |\n+-----+\n";
10         }else if(d < 60){
11             cout << "+-----+\n|-   E|\n|--   |\n|     |\n|     |\n|     |\n+-----+\n";
12         }else if(d < 80){
13             cout << "+-----+\n|-  3G|\n|--   |\n|---  |\n|     |\n|     |\n+-----+\n";
14         }else if(d < 90){
15             cout << "+-----+\n|-  3G|\n|--   |\n|---  |\n|---- |\n|     |\n+-----+\n";
16         }else if(d < 100){
17             cout << "+-----+\n|-  4G|\n|--   |\n|---  |\n|---- |\n|     |\n+-----+\n";
18         }else if(d == 100){
19             cout << "+-----+\n|-  4G|\n|--   |\n|---  |\n|---- |\n|-----|\n+-----+\n";
20         }
21     }
22     return 0;
23 }

 

涛神的城堡

Problem Description

涛神有一个城堡给游客参观,涛神特别的强壮,涛神的强壮值是strong,每个游客也有自己的强壮值,涛神为了赚钱,他会选取多个区间去打劫别人,所以如果比涛神弱的,他就要收取他们的强壮值的差值,但是还是有比涛涛强壮的,所以涛涛打劫那个人的话,涛涛要给那个人他们的强壮值的差值,所以涛涛可以选择打不打劫那个区间的人,(人是可以重复打劫的,区间不行)涛涛最多能赚多少钱呢?

Input

第一行给你三个整型变量n,m,strong(1≤n,m≤10000,1≤strong≤200),
第二行给你n个人的强壮值a1,a2,...,an(1≤ai≤200).
接下来m行给你两个整型变量l,r(1≤li≤ri≤n),代表区间里包括了第l个游客到第r个游客,涛涛可以选择打不打劫这个区间

Output

输出涛涛可以打劫到的最多的钱

Sample Input

5 4 10
9 12 9 7 14
1 2
4 5
3 4
1 4

Sample Output

7
这题有毒,题目说区间不行,但必须按可以取重复的区间才能AC。
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #define ll long long
 5 using namespace std;
 6 const int MAX = 10010;
 7 ll sum[MAX], str;
 8 int main() {
 9     std::ios::sync_with_stdio(false);
10     int n, m;
11     while(cin>>n>>m>>str) {
12         ll x;
13         for(int i = 1; i <= n; i ++) {
14             cin >> x;
15             sum[i] = sum[i-1] + str - x;
16         }
17         ll ans = 0;
18         while(m--) {
19             int l, r;
20             cin >> l >> r;
21             ll y = sum[r] - sum[l-1];
22             if(y > 0) ans += y;
23         }
24         cout << ans << endl;
25         memset(sum,0,sizeof(sum));
26     }
27 }

 

dada的GCD

Problem Description

C语言都学过了怎么计算两个数的最大公约数,而一段区间[L,R]的GCD即这段区间所有数的最大公约数。现在给你一串长度为n的序列,如果对于序列的任意子区间[L,R],都有这段区间的gcd>=2,那么这段序列就叫做dada的GCD序列。
n<=10^4
序列的每个数小于10^9

Input

第一行有一个整数t,代表t组数据
每组输入有一个正整数n,
随后一行n个正整数。

大量输入,使用cin的同学请关闭stdio同步

Output

如果是dada的GCD序列,就输出Yes,反之输出No

Sample Input

2
3
2 6 4
3
4 6 9

Sample Output

Yes
No
语文水平有待提高了,竟然没看懂题意,写了几次都是靠猜的,赛后猜知道要全部的最大公约数大于等于2就行。
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 #define ll long long
 6 using namespace std;
 7 const int MAX = 1e5;
 8 ll a[MAX];
 9 ll gcd(ll a, ll b){
10     return b?gcd(b,a%b):a;
11 }
12 int main() {
13     std::ios::sync_with_stdio(false);
14     int t, n;
15     cin>>t;
16     while(t--) {
17         cin>>n;
18         for(int i = 1; i <= n; i ++) {
19             cin >> a[i];
20         }
21         if(n == 1){
22             if(a[0] >= 2) puts("Yes");
23             else puts("No");
24         }else {
25             ll ans = gcd(a[0],a[1]);
26             for(int i = 2; i <= n; i ++) ans = gcd(ans,a[i]);
27             if(ans >= 2)puts("Yes");
28             else puts("No");
29         }
30     }
31     return 0;
32 }

 

posted @ 2017-07-29 20:31  starry_sky  阅读(343)  评论(0编辑  收藏  举报