連結:https://ac.nowcoder.com/acm/contest/392#question
來源:牛客網
文章目錄
- 華華聽月月唱歌(貪心)
- 華華教月月做數學(Java大數,快速幂+快速乘模闆)
- 華華給月月出題(線性篩法,快速幂)
- 華華給月月準備禮物(二分)
- 華華開始學資訊學(樹狀數組)
- 華華對月月的忠誠(最大公約數)
- 華華和月月逛公園(tarjan算法)
- 月月查華華的手機(STL專題之string的應用)
華華聽月月唱歌(貪心)
?題目位址:https://ac.nowcoder.com/acm/contest/392/A ?
一道簡單的貪心,做炸了,選擇最右端區間的時候沒有維護好,隻過了70%的資料.這道題的解法是先将區間排序,然後周遊這些區間,對于有重合的區間,我們就選擇右端點最遠的區間即可.
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
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;
}
華華教月月做數學(Java大數,快速幂+快速乘模闆)
?題目位址: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<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
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<cstdio>
#include<iostream>
#include<vector>
#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<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
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 <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
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<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
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;
}
華華和月月逛公園(tarjan算法)
?題目位址:https://ac.nowcoder.com/acm/contest/392/I ?
月月查華華的手機(STL專題之string的應用)
?題目位址:https://ac.nowcoder.com/acm/contest/392/J ?
string中find的神奇應用,不過不知道為什麼
1012
沒有逾時.應該還有其他解法.
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
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;
}