最小的数
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中。
接下来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的序列
结合每个情况可以发现
-
- dp[i][0]可以由dp[i-1][0]+dp[i-1][1]+dp[i-1][2]转变过来,因为前一状态只要不是有了3个连续的U的序列,在最右边加一个L就可以形成
- dp[i][1]可以由dp[i - 1][0]转变过来,因为只能是在最右边没有U的序列加上个U形成
- dp[i][2]可以由dp[i - 1][1]转变过来,因为只能是在最右边有一个U的序列加上个U形成
- 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
已知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 像素的图案。
+-----+
|- 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个游客,涛涛可以选择打不打劫这个区间
第二行给你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
n<=10^4
序列的每个数小于10^9
Input
第一行有一个整数t,代表t组数据
每组输入有一个正整数n,
随后一行n个正整数。
大量输入,使用cin的同学请关闭stdio同步
每组输入有一个正整数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 }