牛客周赛31(A-E)

1.A

签到题,没啥好说的

#include
using namespace std;
#define int long long
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    string s;
    cin>>s;
    if(s=="kou")
    cout<<"yukari";
    else
    cout<

2.B 

分解质因数,这个比较重要,i从2遍历到根号x即可,遇到因子i,就除i,不用判断素性,因为一个合数为若干个质数的乘积,遇到一个质因子,再除掉他,在遇到合因子前就被破坏掉了.例如12=2*2*3,遇到素因子而后,4和6都被破坏掉了,最后如果x大于1,说明x有一个大于根号x的因子,只能有一个,两个乘积就会大于x

#include
using namespace std;
#define int long long
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int x;
    cin>>x;
    int cnt=0;
    for(int i=2;i*i<=x;i++)
    {
        if(x%i==0)
        {
            cnt++;
            while(x%i==0)x/=i;
        }
    }
    if(x>1)cnt++;
    cout<

3.C

这个就是找出c,然后向左向右扩展

#include
using namespace std;
#define int long long
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int n;
    char c;
    cin>>n>>c;
    string s;
    cin>>s;
    int ans=0;
    for(int i=0;i

4.D

这题就是考链表,一种方法是list类加一个储存迭代器的数组,另一种方法是静态链表,这个题也比较重要

list类加迭代器数组

#include
using namespace std;
//#define int long long
const int maxn=1e5+5;
map::iterator>pos; 
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int q,op,x,y;
    cin>>q;
    listquelist;
    quelist.push_back(0);
    pos[0]=quelist.begin();
    for(int i=0;i>op;
        if(op==1)
        {
            cin>>x>>y;
            auto iter=next(pos[y]);
            pos[x]=quelist.insert(iter,x);
        }
        else if(op==2)
        {
            cin>>x;
            quelist.erase(pos[x]);
        }
    }
    cout<

静态链表

#include
using namespace std;
#define int long long
mappre,nxt;
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    nxt[0]=pre[0]=0;
    int q,x,y,op;
    cin>>q;
    while(q--)
    {
        cin>>op;
        if(op==1)
        {
            cin>>x>>y;

            pre[x]=y;
            nxt[x]=nxt[y];
            pre[nxt[y]]=x;
            nxt[y]=x;
        }
        else if(op==2)
        {
            cin>>x;
            pre[nxt[x]]=pre[x];
            nxt[pre[x]]=nxt[x];
            pre.erase(x);
            nxt.erase(x);
        }
    }
    cout<

5.E

这个题是变种01背包,然后因为有负数,所以要进行偏移,本来是-40000到40000,要偏移到0到80000,因为数组下标不能有负数,dp[i][j]的含义是处理完1-i的数,装满容量为j的背包的最小操作数.

#include
using namespace std;
#define int long long
int dp[205][80005],m=40000;//处理完1-i的数后,和为j的最小值
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int n;
    cin>>n;
    memset(dp,0x3f,sizeof(dp));
    dp[0][m]=0;
    for(int i=1;i<=n;i++)
    {
        int x;
        cin>>x;
        for(int j=0;j<=2*m;j++)
        {
            if(j+x<=2*m&&j+x>=0)dp[i][j]=min(dp[i][j],dp[i-1][j+x]+1);//减x
            if(j-x>=0&&j-x<=2*m)dp[i][j]=min(dp[i][j],dp[i-1][j-x]);
        }
    }
    if(dp[n][m]>n)dp[n][m]=-1;
    cout<

6.F

隔板法+算组合数

#include
using namespace std;
/*
C(n,m)=n!/(m!*(n-m)!)
*/
long long jc[11010];
const int mod=1e9+7;
long long power(long long a,int b){
    long long res=1;
    while(b){
        if(b&1)res=res*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return res;
}//快速幂
int inv(int x){
    return power(x,mod-2);//求乘法逆元
}
long long C(int n,int m){
    if(m<0||n-m<0)return 0;
    return jc[n]*inv(jc[m])%mod*inv(jc[n-m])%mod;//乘一个数的乘法逆元等于除以它,以此算组合数
}
int main(){
    int i;
    jc[0]=1;
    for(i=1;i<=2000;i++){
        jc[i]=jc[i-1]*i%mod;//预处理阶乘数组
       //invjc[i]=inv(jc[i]);
    }
    int x,y;
    cin>>x>>y;
    for(i=1;i<=x+y;i++){
        int ji=i/2+i%2,ou=i/2;//ji向上取整
        cout<<(C(x-1,ji-1)*C(y-1,ou-1)+C(y-1,ji-1)*C(x-1,ou-1))%mod<<'\n';
    }
}

你可能感兴趣的:(动态规划,c++,算法)