F. 程序设计:找质数
数据范围
对于 30\%30% 的数据 1 \le t \le 10^31≤t≤103。
对于 60\%60% 的数据 1 \le t \le 10^51≤t≤105。
对于 100\%100% 的数据 1 \le t \le 10^6, 4 \le n \le 10^61≤t≤106,4≤n≤106,nn 为偶数。
由于本题的数据范围过大,需要对素数预处理,普通的素数打表会TLE
所以我使用素数筛选法打表:
素数筛选法 详细解释
void isPrime ()
{
memset(prim,0,sizeof(prim));
prim[0]=prim[1]=1;
for(int i=2; i*i <= maxn; i++)
if(prim[i]==0)
{
for(int j=i+i;j<=maxn;j+=i)
prim[j]=1;
}
}
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int prim[maxn]; //存储素数序列
void isPrime () //将素数都标记为0
{
memset(prim,0,sizeof(prim)); //不初始化也可以 全局的数组已经被赋值为0
prim[0]=prim[1]=1; // 0和1不是素数
for(int i=2; i*i <= maxn; i++)
if(prim[i]==0)
{
for(int j=i+i;j<=maxn;j+=i)
prim[j]=1;
}
}
//用cin过不了
int main()
{
isPrime();
int n,num;
scanf("%d",&n);
while(n--)
{
scanf("%d",&num);
for(int i=2;;i++)
{
if(!prim[i]&&!prim[num-i]) //卡条件
{
printf("%d %d\n",i,num-i);
break;
}
}
}
return 0;
}
G. 程序设计:后缀字符串
该题有点坑,第一次我用得是暴力模拟,就是简单的在双重for循环中判断是否存在字符串后缀
暴力模拟:(过了50%的测试点)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
string str[maxn];
int main()
{
std::ios::sync_with_stdio(false);
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>str[i];
for(int i=0;i<n;i++)
{
int ans=0;//每次都初始化为0
for(int j=0;j<n;j++)
{
int pos=str[j].length()-str[i].length();
int flag=1;
if(pos<0) //后一个字符长度小于前一个就一定不能包含前一个
continue;
for(int k=0;k<str[i].length();k++)//开始查询
{
if(str[i][k]!=str[j][pos+k])//如果不是后缀
{
flag=0;
break;
}
}
if(flag) ans++;
}
cout<<ans<<endl;
}
return 0;
}
2.使用map容器,由于map容器由键(key)和值(value)构成一对单元,key 和 value可以是任意你需要的类型。
这种关联类容器可以使得操作的时间复杂度大大降低
官方题解使用了substr:
substr的2种用法:
假设:string s = "0123456789";
string s1 = s.substr(7); //表示从下标为7开始一直到结尾:s1 = "789"
string s2 = s.substr(7, 2); //从下标为5开始截取长度为2位:s2 = "78"
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+5;
string a[N];
int main() {
map<string, int> mp;
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> a[i];
for (int j = 0; j < a[i].size(); j++)
{
mp[a[i].substr(j)]++;
}
}
for (int i = 0; i < n; i++)
{
cout << mp[a[i]] << endl;
}
return 0;
}
H. 程序设计:轻重搭配
采用贪心策略,要注意先对体重进行升序排序,然后再将第1轻的人与第n/2轻的人进行配对,如果满足条件则配对成功,所需门票数减一,且pos后移。若不满足条件则pos后移,将第1轻的人与第n/2 +1 轻的人进行配对,依次类推
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
int main()
{
std::ios::sync_with_stdio(false);
int n;
int a[maxn];
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n); //按体重排序
int pos=n/2,couple=n; //pos是搜索的起点,couple是所需的门票数
for(int i=0;i<n/2;i++)
{
while(a[i]*2>a[pos] && pos<n) //如果不满足条件,pos后移
pos++;
if(pos==n) //搜索完毕,及时退出
break;
if(a[i]*2<=a[pos]) //满足条件
{
couple--; //门票数减一
pos++; //注意pos的后移,搜索下一配对
}
}
cout<<couple<<endl;
return 0;
}