2021牛客寒假算法训练营1

比赛地址

A 串

解法一:数学递推

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>

using namespace std;

typedef long long ll;

const ll mod=1e9+7;

const int N=1e6+10;
ll dp[N];

ll quick_pow(ll x,ll y)
{
    ll ans=1;
    while(y){
        if(y&1)ans=(ans*x)%mod;
        x=(x*x)%mod;
        y>>=1;
    }
    return ans%mod;
}

int main()
{
    int n;
    cin>>n;
    dp[2]=1;
    for(int i=3;i<=n;i++){
        ll num=(quick_pow(26,i-1)-quick_pow(25,i-1))%mod;
        dp[i]=(num+25*dp[i-1]+mod)%mod;//+mod
    }
    ll ans=0;
    for(int i=2;i<=n;i++)ans=(ans%mod+dp[i]%mod)%mod;
    cout<<ans<<endl;
    return 0;
}

解法二:DP

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>

using namespace std;

typedef long long ll;

const ll mod=1e9+7;

const int N=1e6+10;
ll dp[N][3];

int main()
{
    int n;
    cin>>n;
    dp[1][0]=25,dp[1][1]=1,dp[1][2]=0;
    for(int i=2;i<=n;i++){
        dp[i][0]=dp[i-1][0]*25%mod;
        dp[i][1]=(dp[i-1][1]*25%mod+dp[i-1][0]%mod+mod)%mod;
        dp[i][2]=(dp[i-1][2]*26%mod+dp[i-1][1]%mod+mod)%mod;
    }
    ll ans=0;
    for(int i=2;i<=n;i++)ans=(ans%mod+dp[i][2]%mod+mod)%mod;
    cout<<ans<<endl;
    return 0;
}

B括号
思路:构造,先初始化构造一个有sqrt(n)个’(‘和sqrt(n)个’)‘的串,该串长度为2sqrt(n),数据范围到1e9,则长度为2*31622约为6e4,题目要求范围不超过1e5,符合要求,此时构造的串得出的合法括号对数为int(sqrt(n)*sqrt(n)),还需要的括号对数为ans=n-(int)(sqrt(n)*sqrt(n)),对于左边的每个左括号’(‘在第几个左括号后增加一个右括号’)'贡献出的对数就为几,则在几个左括号后边增加了几个(假设是m个)右括号增加对数为m * (m+1) / 2,这样找到一个使得增加后的总和不大于ans的最大的m后剩下离ans还缺几个就在第几个左括号后增加一个右括号即可

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>

using namespace std;

int main()
{
    int n;
    cin>>n;
    if(n==0){
        cout<<")("<<endl;
        return 0;
    }
    string s="";
    int ans=sqrt(n);
    int tmp=n-ans*ans;
    for(int i=1;i<=ans;i++)s+='(';
    for(int i=1;i<=ans;i++)s+=')';
    int num=0;
    while(tmp){
        for(int i=0;i<ans;i++){
            if((i+1)*(i+2)/2>tmp)break;
            num=i+1;
        }
        tmp-=num*(num+1)/2;
        int tp=0;
        for(int i=0;i<s.size();i++){
            if(s[i]=='('&&tp<num)s.insert(i+1,1,')'),tp++;
        }
    }
    cout<<s<<endl;
    return 0;
}

F对答案一时爽
思路:简单思维题,每道题的答案和得分是独立的,对每道题如果两个人答案相同,最大值自然是两个人都对,_mx+=2,否则最大值_mx+=1,最小值自然是两个人都错,_mn=0

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>

using namespace std;

const int N=110;
char a[N],b[N];

int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)cin>>a[i];
    for(int i=0;i<n;i++)cin>>b[i];
    int _mx=0,_mn=0;
    for(int i=0;i<n;i++){
        if(a[i]==b[i])_mx+=2;
        else _mx++;
    }
    cout<<_mx<<' '<<_mn<<endl;
    return 0;
}

H 幂塔个位数的计算
思路:规律

a=int(input())
b=int(input())
ans=a%10

#个位数是0
if not ans or ans==1 or ans==5 or ans==6 or ans==9:print(ans)
elif b==1:print(a%10)
elif ans==2 or ans==8:
    ans=a%100%4
    if b==2 and ans!=0:print(4)
    else :print(6)
elif ans==3:
    ans=a%4
    if ans==3:print(7)
    else :print(3)
elif ans==4:
    print(6)
elif ans==7:
    ans=a%4
    if ans==3:print(3)
    else :print(7)

I限制不互素对的排列
思路:构造,因为题目给定了k肯定不大于n/2,那么构造不互素排列很简单,只要把1-n中的偶数排前面一直到达到k对相邻不互素,当小于n/2的时候只要把相应个数的偶数排前面奇数排后面,剩下的数再接在奇数后面就可以,如果k达到n/2时,把所有的偶数排前面仍然还缺一个,此时只要对最后一个偶数分解约数返回还未遍历过的一个约数即可,将这个约数(一定要让他大于1)放在这个偶数的后面,剩下的数往后面接着排即可,这样就构造完成了

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<string>
#include<vector>
#include<algorithm>

using namespace std;

const int N=1e5+10;
bool vis[N];
vector<int> v;

int get_divisors(int n)
{
    for(int i=2;i<=n/i;i++){
        if(n%i==0){
            if(!vis[i]){
                vis[i]=true;
                return i;
            }
            if(i!=n/i){
                if(!vis[n/i]){
                    vis[n/i]=true;
                    return n/i;
                }
            }
        }
    }
    return 0;
}

int main()
{
    int n,k;
    cin>>n>>k;
    int cnt=0;
    memset(vis,false,sizeof(vis));
    for(int i=2;i<=n;i+=2){
        if(cnt>k)break;
        v.push_back(i);
        vis[i]=true;cnt++;
    }
    int num=0;
    if(n&1)num=n-1;
    else num=n;
    //cout<<num<<endl;
    if(vis[num]&&k>=n/2){
        num=get_divisors(num);
        //cout<<num<<endl;
        v.push_back(num);
    }
    for(int i=1;i<=n;i++){
        if(!vis[i])v.push_back(i);
    }
    for(int i=0;i<v.size();i++){
        if(!v[i]){
            cout<<"-1"<<endl;
            return 0;
        }
    }
    for(int i=0;i<v.size();i++)cout<<v[i]<<' ';
    return 0;
}

J 一群小青蛙呱蹦呱蹦呱
思路:线性筛+数学推导

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<map>

using namespace std;

typedef long long ll;
const ll mod=1e9+7;

const int N=8e7+100;
int primes[N],cnt;
bool vis[N];
int n;

ll quick_pow(ll x,ll y)
{
    ll res=1;
    while(y){
        if(y&1)res=(res*x)%mod;
        x=(x*x)%mod;
        y>>=1;
    }
    return res%mod;
}

ll cal(int i)
{
    int k;
    if(i==2)k=floor(log(n/3)/log(2));
    else k=floor(log(n/2)/log(i));
    ll res=quick_pow(i*1ll,k*1ll)%mod;
    return res%mod;
}

ll get_primes(int n)
{
    ll ans=1;
    for(int i=2;i<=n/2;i++){
        if(!vis[i]){
            primes[cnt++]=i;
            ans=(ans*cal(i))%mod;
        }
        for(int j=0;primes[j]<=n/2/i;j++){
            vis[i*primes[j]]=true;
            if(i%primes[j]==0)break;
        }
    }
    return ans%mod;
}

int main()
{
    cin>>n;
    ll ans=get_primes(n);
    if(ans>1)cout<<ans<<endl;
    else cout<<"empty"<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值