1.对于一个字符串 S ,我们定义 f(S)为 S�中出现的不同的字符个数。 例如 f(aba)=2,f(abc)=3,f(aaa)=1。
现在给定一个字符串 S (假设长度为 len),请你计算 ∑i=0len−1∑j=ilen−1f(S[i:j]))。
#include <iostream>
#include <string.h>
#include <cstring>
using namespace std;
const int N = 1e6 + 5;
string s;
long long a[28], b[N], c, x, y, z, sum;
long long ans;
int main()
{
cin >> s;
c = s.length();
for (int i = 0; i < c; i++)//先求出从第一个字母开始的字串和
{
if (a[s[i] - 96] == 0)
{
sum++;
a[s[i] - 96] = 1;
}
ans += sum;
}
b[0] = ans;
for (int i = 1; i < c; i++)
{
b[i] = b[i - 1] - 1;
for (int j = i; j < c; j++)
{
if (s[j] != s[i-1])//从第二个字母开始,其字串如果出现了与前一个字母相同的字母,那么该字串后面与前一个字母从这开始的字串相同
b[i]--;
else
break;
}
ans += b[i];
}
cout << ans;
return 0;
}
2. 便利蜂的货架上摆了一排蒟蒻果冻,搞得鶸尛鱻眼花缭乱......
对于每个果冻,都有一个价格 w和口感 t。鶸尛鱻有一个购物篮子,在挑选蒟蒻果冻的时候,他有以下几种操作:
- 操作 11:把一个价格为 w,口感为 t 的果冻放入篮子。
- 操作 22:拿出篮子中 最为廉价 的果冻。
- 操作 33:拿出篮子中 口感最差 的果冻。(t 越小,口感越差)
鶸尛鱻不喜欢重复,当操作 11 的 价格或口感 与篮中已有果冻重复时,他会立刻将其放回货架。
经过 n 次操作后,鶸尛鱻确定了要购买的若干果冻,请你帮他求出篮子里果冻的总价格。
本题了解map函数的基本用法即可解决
#include <iostream>
#include <map>
using namespace std;
#define int long long
const int mod=1e9+7;
map<int,int>mp1;
map<int,int>mp2;
void solve()
{
int op,val,wa;
cin>>op;
if(op==1)
{
cin>>val>>wa;
if(mp1.count(val)==0 && mp2.count(wa)==0)
{
mp1[val]=wa;
mp2[wa]=val;
}
}
else if(op==2)
{
mp2.erase(mp1.begin()->second);
mp1.erase(mp1.begin());
}
else if(op==3)
{
mp1.erase(mp2.begin()->second);
mp2.erase(mp2.begin());
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin>>t;
while(t--)
{
solve();
}
int ans=0;
for(auto x:mp1)
{
ans+=x.first;
}
cout<<ans<<endl;
return 0;
}
3.
有n个玩家参加比赛,他们分别有能力值a1,a2,…,an。
需要进行n−1轮比赛,每一轮在剩下的玩家里任选两个玩家i,j。如果|ai−aj|>K,那么其中能力值高的玩家会获胜,能力值低的玩家会被淘汰。如果|ai−aj|≤K,那么两个玩家都有可能获胜,另一个玩家被淘汰。
n−1轮比赛之后,只剩下一个玩家。问有多少个玩家可能是最后获胜的玩家。
本题较为简单,对玩家能力值进行排序后,由大往小减,如果该数减去小于他的数大于k,他就能获胜,且能力值比他小的人不可能再获胜,如果小于等于k的话,则两人都有可能获胜。
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5 + 5;
int a[N], n, k, ans=1;
int main()
{
cin >> n >> k;
for (int i = 1; i <= n; i++)
cin >> a[i];
sort(a+1, a + n + 1);
for (int i = n; i >= 2; i--)
{
if (a[i] - a[i - 1] <=k)
ans++;
else
break;
}
cout << ans;
}
4.
请按字典序从小到大的顺序输出所有序列,满足序列中有 p1个 1, p2个 2, ……, pn 个 n。
本题掌握dfs的基本使用方法即可
#include <iostream>
using namespace std;
int n,a[10],c,p[100],sum;
void dfs(int x)
{
if (x == sum + 1)
{
for (int i = 1; i <= c; i++)
cout << p[i] << " ";
cout << '\n';
}
else
{
for (int i = 1; i <=n; i++)
{
if (a[i] != 0)
{
a[i]--;
c++;
p[c] = i;
dfs(x + 1);
c--;
a[i]++;
}
}
}
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
sum += a[i];
}
dfs(1);
return 0;
}
5.
以不同进制的形式输入 n 个非负整数,求出它们的和并以 m进制的形式输出。
使用大写字母 A
~ Z
依次代表 10 ~ 35, 小写字母 a
~ z
依次代表 36 ~ 61。
本题较为简单,掌握进制转换规律即可
#include <iostream>
#include <string.h>
using namespace std;
long long n, m, x,a[10000],sum;
string s;
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
long long p = 1;
cin >> x >> s;
for (int i = s.length()-1; i >=0; i--)
{
if (s[i] >= 'A' && s[i] <= 'Z')
sum += p * (s[i] - 55);
else if (s[i] >= 'a' && s[i] <= 'z')
sum += p * (s[i] - 61);
else
sum += p * (s[i] - 48);
p *= x;
}
}
int q = 1;
a[q] = sum;
while (1)
{
a[q + 1] = a[q] / m;
a[q] = a[q] % m;
q++;
if (a[q] < m)
{
break;
}
}
for (int i = q; i >= 1; i--)
{
if (a[i] >= 10 && a[i] <= 35)
{
char f = a[i] + 55;
cout << f;
}
else if (a[i] >= 36 && a[i] <= 61)
{
char f = a[i] + 61;
cout << f;
}
else
cout << a[i];
}
return 0;
}
6.
一个字符串S是另一字符串T的循环子串当且仅当存在k, T所有字符循环右移k位后得到的新串T′,满足S是T′的子串。
例如: abc
是 cefab
的循环子串。 (cefab
循环右移22位得到abcef
, abc
是abcef
的子串)
一个串P是完全循环串当且仅当对于它的任一子串H, 都有Hreverse是P的循环子串 (Hreverse 为 H的倒转, 如abc
reverse后 为cba
)。
给一个长度为n的字符串, 判断它是不是完全循环串。
本题意思就是说,字符串s的所有子串翻过来之后(abc变cba)能在s里找到一样的字符串,这个s可以是向右移动k次之后的样子(向右移动k次相当于把前面k个字符移动到末尾,比如abcde移动2次,那就变成cdeab)。
那么我们只要枚举所有可能的子串,然后在旋转后的字符串s里找看是不是都能找到即可,如果都能找到那就输出yes,一个找不到都要输出no。可是每次都要移动字符串s太麻烦了,所以我们要对字符串做点改变。
就像我们前面说的,移动k次是把前k个字符删除移动到末尾,那么最多移动len(字符串长度)次,字符串就会变回原样,那我们直接把一个相同的字符串s接到s后面即可,这样就可以在这个字符串里找到所有可能移动过后的字符串s,我们在这里面找子串即可。
#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
using namespace std;
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
typedef long long ll;
typedef pair<ll, ll>PII;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
{
int n;
string s;
cin >> n >> s;
bool flag = true;
string str = s + s;
for (int len = 2; len <= n; len++)
{
for (int i = 0; i + len <= n; i++)
{
string res = s.substr(i, len);
reverse(res.begin(), res.end());
if (str.find(res) == str.npos)
{
cout << "NO" << endl;
flag = false;
break;
}
}
if (!flag)break;
}
if (flag)cout << "YES" << endl;
}
return 0;
}
7.
晚上,游乐园晚上的party就开始啦,其中有一个游戏环节,赢的人可以得到免费的西瓜,饿到不行的cc和他的小伙伴非常希望得到这个西瓜。
包括cc和他的小伙伴,有t个玩家参与了这个游戏,每个玩家都有一张带有数字的卡片。第i张卡片上有ni个数字,分别是m1,m2,...mn。
游戏过程中,主持人从袋子里一个一个地取出编号的球。 他用洪亮而清晰的声音大声念出球的编号,然后把球收起来。 如果玩家的卡片上有对应的数字,就可以将它划掉。 最先从他的卡片上划掉所有数字的人获胜。 如果多人同时从他们的卡片上划掉所有数字,那么这些人都不能赢得比赛。 在游戏开始时,袋子里有 100 个球,编号从 1 到 100,所有球的编号都是不同的。
cc偷偷知道了每个玩家的数字。 想请你确定每个玩家是否可以在最有利于他的情况下赢得比赛。
想要有利的情况下自己胜出,也就是说选出的数都是自己有的,而且自己在第一个清空前不能有别人比自己先清空。
意思就是自己不能包含别人的全部数:别人不能是自己的子集。比如自己是1 3 5,别人是3 5,那么最好的情况也是别人和我一起清空,这样两边都不能赢,如果自己是1 3 5,别人是3 4,那我只要不删4就行了,这样就是我先赢。
那么我们就记录每个玩家的牌的情况,然后判断我们的牌是否完全包含其它玩家的牌,如果有一个完全包含那我们就不能赢。
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int a[105][105], n, x[105], y[105],z[105];
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> x[i];
for (int j = 1; j <= x[i]; j++)
{
cin >> a[i][j];
if (z[a[i][j]] == 1)
{
x[i]--;
j--;
}
z[a[i][j]] = 1;
}
sort(a[i] + 1, a[i] + x[i] + 1);//排序
memset(z, 0, sizeof(z));
}
for (int i = 1; i <= n; i++)
{
for (int j = i + 1; j <= n; j++)//判断两者是否有重叠
{
int f = 1;
if (x[i] == x[j])
{
for (int t = 1; t <= x[i]; t++)
{
if (a[i][t] != a[j][t])
{
f = 0;
break;
}
}
if (f == 1)
{
y[i] = 1;
y[j] = 1;
}
}
else if (x[j] > x[i])
{
int jj = 1, ii = 1;
if (y[j] == 0)
{
while (1)
{
if (a[i][ii] == a[j][jj])
ii++;
jj++;
if (ii == x[i] + 1)
{
f = 0;
break;
}
if (jj == x[j] + 1)
break;
}
if (f == 0)
y[j] = 1;
}
}
else
{
int jj = 1, ii = 1;
if (y[i] == 0)
{
while (1)
{
if (a[i][ii] == a[j][jj])
jj++;
ii++;
if (jj == x[j] + 1)
{
f = 0;
break;
}
if (ii == x[i] + 1)
break;
}
if (f == 0)
y[i] = 1;
}
}
}
}
for (int i = 1; i <= n; i++)
{
if (y[i] == 1)
cout << "NO" << '\n';
else
cout << "YES" << '\n';
}
return 0;
}
8.
RSA算法选择两个不同质数的积作为模数。现在有两个正整数 A,B,如果它们是不同的质数,则判定为 full credit
;否则,如果A⋅B不是任意大于1的整数的平方的整数倍,则判定 partial credit
;否则判定为no credit
。
本题了解如何判断一个数为质数的简单方法即可
#include <iostream>
#include <math.h>
using namespace std;
long long x, y, z, ans, a, b, c;
int zhi(long long x)//较为便捷的判断一个数是否为质数
{
if (x == 1)
return 0;
if (x == 2)
return 1;
for (int i = 2; i < sqrt(x) + 2; i++)
{
if (x % i == 0)
return 0;
}
return 1;
}
int main()
{
cin >> a >> b;
if (sqrt(a) == floor(sqrt(a)) || sqrt(b) == floor(sqrt(b)))
{
cout << "no credit";
}
else
{
if (zhi(a) == 1)
{
if (zhi(b) == 1)
{
if (a == b)
cout << "no credit";
else
cout << "full credit";
}
else
{
if (b % a == 0)
cout << "no credit";
else
cout << "partial credit";
}
}
else if (zhi(b) == 1)
{
if (a % b == 0)
cout << "no credit";
else
cout << "partial credit";
}
else
{
if (a == b)
cout << "no credit";
else
{
if (b > a)
{
z = b;
b = a;
a = z;
}
x = 0;
long long i = 2;
z = b / 2 + 1;;
while (i < z)
{
if (a % i == 0)
{
z = a / i;
if (b % i == 0 || b % z == 0)
{
x = 1;
cout << "no credit";
}
}
i++;
}
if (x == 0)
cout << "partial credit";
}
}
}
}
9.
给出一串数以及一个数字 C ,要求计算出所有 A−B=C 的数对的个数(不同位置的数字一样的数对算不同的数对)。
输入格式
输入共两行。
第一行,两个整数 N, C。
第二行, N 个整数,作为要求处理的那串数。
输出格式
一行,表示该串数中包含的满足 A−B=C 的数对的个数。
本题是一道较为简单的数学分析题,从1到n枚举即可
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 2e5 + 5;
int a[N], b[N], c, n, x, ans;;
int main()
{
cin >> n >> c;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
sort(a + 1, a + n + 1);
int p = 2,j;
for (int i = 1; i <= n; i++)
{
while (1)
{
if (p > n)
break;
if (a[p] - a[i] == c)
{
j = i;
int sum = 0;
while (a[p] - a[j] == c)
{
ans++;
j++;
sum++;
}
while (a[p] == a[p + 1])
{
p++;
ans += sum;
}
p++;
break;
}
if (a[p] - a[i] > c)
{
break;
}
p++;
}
if (p == n + 1)
break;
}
cout << ans;
return 0;
}
10.
由于本题的数据范围很大,所以需要用到巧妙的高精度算法
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int main() {
int i, j, k, n, m;
long long f1, f2, f3;
cin >> f1;
n = 0;
for (f2 = 1; f2 < f1; f2 = f2 * 10 + 1)
n++;
while (1)
{
n++;
if (f2 % f1 == 0)
{
cout << f2 / f1; break;
}
else
{
cout << f2 / f1; f2 %= f1; f2 = f2 * 10 + 1; //巧妙的高精度算法
}
}
cout << " " << n << endl;
return 0;
}