链接:https://ac.nowcoder.com/acm/contest/392#question
来源:牛客网
?题目地址:https://ac.nowcoder.com/acm/contest/392/A ?
一道简单的贪心,做炸了,选择最右端区间的时候没有维护好,只过了70%的数据.这道题的解法是先将区间排序,然后遍历这些区间,对于有重合的区间,我们就选择右端点最远的区间即可.
#include
#include
#include
#include
#include
using namespace std;
const int Max_n=100005;
typedef long long LL;
struct A{
int l,r;
}a[Max_n];
bool operator <(const A &a,const A &b){
if(a.l==b.l)
return a.r>b.r;
return a.l<b.l;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d",&a[i].l,&a[i].r);
sort(a+1,a+m+1);
if(a[1].l>1){
printf("-1\n");
return 0;
}
int s=1,e=1,sum=1;
for(int i=1;i<=m;i++){
if(a[i].l<=s)//有多个区间与当前区间重合,找到终点最大的区间.
e=max(e,a[i].r);
else{//如果没有此时没有了重合的区间,就去更新当前区间,继续寻找下一个区间.
sum++;
s=e+1;//未更新过的区间的终点
if(a[i].l<=s) e=max(e,a[i].r);//要选择的下一个区间最右边的点.
else{
printf("-1\n");//没有符合条件的就出现了断层
return 0;
}
}
if(e>=n) break;
}
printf("%d\n",e>=n?sum:-1);
return 0;
}
?题目地址:https://ac.nowcoder.com/acm/contest/392/B ?
java大数无敌,很方便.函数用好就ok.
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int T = in.nextInt();
while(T-->0){
BigInteger a = in.nextBigInteger();
BigInteger b = in.nextBigInteger();
BigInteger mod = in.nextBigInteger();
BigInteger ans = a.modPow(b,mod);
System.out.println(ans);
}
}
}
处理高精度使用快速幂+快速乘
#include
#include
#include
#include
#include
using namespace std;
const int Max_n=100005;
typedef long long LL;
LL q_mul(LL a,LL b,LL mod){//快速乘
LL ans=0,res=a;
while(b){
if(b&1) ans=(ans+res)%mod;
res=(res+res)%mod;
b>>=1;
}
return ans;
}
LL q_pow(LL a,LL b,LL mod){//快速幂
LL ans=1,res=a;
while(b){
if(b&1) ans=q_mul(ans,res,mod);
res=q_mul(res,res,mod);
b>>=1;
}
return ans;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
LL a,b,mod;
scanf("%lld%lld%lld",&a,&b,&mod);
LL ans=q_pow(a,b,mod);
printf("%lld\n",ans);
}
return 0;
}
?题目地址:https://ac.nowcoder.com/acm/contest/392/C ?
?积性函数:https://baike.baidu.com/item/积性函数/8354949?fr=aladdin ?
?线性筛法:https://blog.csdn.net/qq_42217376/article/details/88418482 ?
如题:
xn就是一个积性函数,再加上线性筛即可解决此问题
这个题,我所有的数据类型都用的LL一直内存超限,后来改成了int过了,原因不详.
#include
#include
#include
#define mod 1000000007
using namespace std;
const int Max_n=13000010;
typedef long long LL;
int f[Max_n],n;
bool is_prime[Max_n];
vector<int>prime;
int q_pow(int a,int b){
int ans=1,res=a;
while(b){
if(b&1) ans=(1LL*ans*res)%mod;
res=(1LL*res*res)%mod;
b>>=1;
}
return ans;
}
int main(){
scanf("%d",&n);
LL ans=0;
for(int i=2;i<=n;i++) is_prime[i]=true;
for(int i=2;i<=n;i++){
if(is_prime[i]){
prime.push_back(i);
f[i]=q_pow(i,n);
}
for(int j=1;j<(int)prime.size();j++){
if(i*prime[j]>n) break;
is_prime[i*prime[j]]=false;
f[i*prime[j]]=(1LL*f[i]*f[prime[j]])%mod;//保证每个数只被计算一次
if(i%prime[j]==0) break;
}
ans^=f[i];
}
printf("%lld\n",ans^1);
return 0;
}
?题目地址:https://ac.nowcoder.com/acm/contest/392/E ?
直接二分棍子的长度,然后找到最长的即可.
#include
#include
#include
#include
#include
using namespace std;
const int Max_n=100005;
typedef long long LL;
int a[Max_n],n,k;
bool check(int mid){
int cnt=0,flag=false;
for(int i=1;i<=n;i++){
cnt+=a[i]/mid;
if(cnt>=k){//能够分解成k根
flag=true;
break;
}
}
return flag;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int l=1,r=1000000000,ans=0;
while(l<=r){//二分长度
int mid=l+(r-l)/2;
if(check(mid)){//当前长度能够分解成k根,长度还可以增加.
l=mid+1;
ans=mid;
}else{
r=mid-1;
}
}
printf("%d\n",ans);
return 0;
}
?题目地址:https://ac.nowcoder.com/acm/contest/392/F ?
?实在看不懂题解说的上限,看着别人写(代码+思路)的模仿着敲了两遍,改了n多遍,结果一直只过10%的数据.最后还是放弃,直接树状数组暴力过90%的数据.下面贴出来树状数组模板.
#include
#include
#include
#include
using namespace std;
typedef long long LL;
const int Max_n=100005;
LL d[Max_n];
int n,m;
void add(int x,int v){//单点修改
while(x<=n){
d[x]+=v;
x+=(x&-x);
}
}
LL quary(int x){//计算前缀和
LL ans=0;
while(x){
ans+=d[x];
x-=(x&-x);
}
return ans;
}
int main() {
scanf("%d%d",&n,&m);
while(m--){
int opt,l,r;
scanf("%d%d%d",&opt,&l,&r);
if(opt==1){
for(int i=l;i<=n;i+=l)
add(i,r);
}else{
LL ans=quary(r)-quary(l-1);
printf("%lld\n",ans);
}
}
return 0;
}
?题目地址:https://ac.nowcoder.com/acm/contest/392/G ?
?比赛的时候把gcd函数写错.......
#include
#include
#include
#include
#include
using namespace std;
const int Max_n=100005;
typedef long long LL;
char s[Max_n];
LL gcd(LL a,LL b){
if(a<b){LL t=a;a=b;b=t;}
return b==0?a:gcd(b,a%b);
}
int main(){
LL a,b;
scanf("%lld%lld",&a,&b);
scanf("%s",s);
LL ans=gcd(a,b);
printf("%lld\n",ans);
return 0;
}
?题目地址:https://ac.nowcoder.com/acm/contest/392/I ?
?题目地址:https://ac.nowcoder.com/acm/contest/392/J ?
string中find的神奇应用,不过不知道为什么
1012没有超时.应该还有其他解法.
#include
#include
#include
#include
#include
#include
using namespace std;
const int Max_n=100005;
typedef long long LL;
int main(){
string a;
int n;
cin>>a>>n;
getchar();
while(n--){
string b;
cin>>b;
bool flag=true;
int len=b.length();
size_t index=a.find(b[0]);//先找到第一个位置.
if(index==a.npos){
cout<<"No"<<endl;
continue;
}
for(int i=1;i<len;i++){
index=a.find(b[i],index+1);
if(index==a.npos){
flag=false;
break;
}
}
if(flag) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}