省赛训练1


B - C HDU - 6025

题意:给你一个最大公约数为1的序列,选择其中一个去掉,使得剩余序列最大公约数最大。输出最大公约数

思路:一开始想的暴力,两重循环,结果一看数据范围,肯定会超时。然后就想怎么能让它简化一重循环?其实就是从前往后一次记录每个位置的前缀最大公约数,然后在从后往前求每个位置的后缀最大公约数,然后再根据每个位置,利用其前缀最大公约数和后缀最大公约数求最大公约数,这样就简化成一重循环。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define M 100005
#define inf 0x3f3f3f3f
int ans;
int n,a[M],b[M],c[M];

int gcd(int a,int b)
{
    return b==0? a : gcd(b,a%b);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)  scanf("%d",&a[i]);
        a[0]=a[n];
        a[n+1]=a[1];

        b[1] = a[1];                   ///qianmian
        c[n] = a[n];               ///houmian

        for(int i=1;i<=n;i++)  b[i] = gcd( b[i-1] , a[i]);

        for(int j=n;j>=1;j--) c[j] = gcd(c[j+1],a[j]);

        ans = -inf;

        for(int i=1;i<=n;i++)
        {

            ans = max(ans,gcd(b[i-1],c[i+1]));
        }

        printf("%d\n",ans);
    }
    return 0;
}

D - E HDU - 6027

题意:

求1-n中每个数的k次方的和,n到10000,用普通方法肯定不行,这里用到快速幂取模

代码:

#include <bits/stdc++.h>
using namespace std;
const long long mod = 1e9+7;

long long quickmi(long long a, long long b){
    long long ans = 1;
    a %= mod;
    while(b){
        if( b & 1 )  ans = (ans*a) % mod;
        b >>= 1;
        a = (a*a) % mod;
    }
    return ans;
}

int main()
{
    int t;
    long long n,k;
    cin>>t;
    while(t--){
        cin>>n>>k;
        long long sum = 0;
        for( long long i = 1; i <= n; i++ )
            sum = (sum + quickmi(i, k)) % mod;

        cout<<sum%mod<<endl;
    }
    return 0;
}

未完待续--------------------------

扫描二维码关注公众号,回复: 1036849 查看本文章
F - G HDU - 6029
题意:
给定图的 n 个顶点以及 a2,a3,...,an 。其中 ai(1≤ai≤2)表示其在图中与其它点的关系:

   1  点 i 与所有标号小于 i 的点均存在一条边。
   2  点 i 与所有标号小于 i 的点都不存在边。

perfect matching 被定义为图中存在一个边集,使得所有顶点有且仅有一条边与之相连。

问对于给定的图,是否存在 perfect matching ?
思维题,代码如下:




#include <bits/stdc++.h>
using namespace std;
int a[100010];

int main()
{
    int t;
    int n;
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(int i=2;i<=n;i++)
        {
            cin>>a[i];
        }
        if(n%2==1)
        {
            cout<<"No"<<endl;
            continue;
        }
        int t=0;
        int s=0;
        int flag=0;
        for(int i=n;i>=2;i--)
        {
            if(a[i]==1)
            {
                t++;
            }
            else if(a[i]==2)
            {
                s++;
            }
            if(t<s)
            {
                flag=1;
                break;
            }
        }
        if(flag==1)
        {
            cout<<"No"<<endl;
        }
        else
        {
            cout<<"Yes"<<endl;
        }
    }
    return 0;
}

G - H HDU - 6030

题意:

给你一个长度为n的序列,每个位置为红色或者蓝色,任意取素数个长度的子序列,均满足红色的个数不小于蓝色,问共有多少种情况?

思路:

规律题,找了好久才发现,一开始理解错题意,后来发现错误,其实1的时候应该是2,虽然n取不到1,然后就会发现规律:

F [ n ] = F [ n - 1 ] + F [ n - 3 ];

然后看了看范围,n的范围是10的18次方,数组肯定存不开,于是想到了矩阵快速幂。下面是代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<math.h>
#include<algorithm>
#include<stack>
using namespace std;
typedef long long ll;
const int mod=1e9+7;


struct matrix
{
    ll m[5][5];
};
matrix mutil(matrix a,matrix b)
{
    matrix c;
    memset(c.m,0,sizeof(c.m));
    for(int i=1;i<=3;i++)
    {
        for(int j=1;j<=3;j++)
        {
            for(int k=1;k<=3;k++)
            {
                c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
            }
            c.m[i][j]%=mod;
        }
    }
    return c;
}
matrix powmod(matrix a,ll k)
{
    matrix ans;
    memset(ans.m,0,sizeof(ans.m));
    for(int i=1;i<=3;i++)
        ans.m[i][i]=1;
    while(k)
    {
        if(k&1)
        {
            ans=mutil(ans,a);
            k--;
        }
        k>>=1;
        a=mutil(a,a);
    }
    return ans;
}
int main()
{
    int t;
    ll n,res;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld",&n);
        if(n==2)
            printf("3\n");
        else if(n==3)
            printf("4\n");
        else if(n==4)
            printf("6\n");
        else
        {
            matrix a,b,c,d;
            a.m[1][1]=1;a.m[1][2]=0;a.m[1][3]=1;
            a.m[2][1]=1;a.m[2][2]=0;a.m[2][3]=0;
            a.m[3][1]=0;a.m[3][2]=1;a.m[3][3]=0;
            memset(c.m,0,sizeof(c.m));
            c.m[1][1]=6;c.m[2][1]=4;c.m[3][1]=3;
            b=powmod(a,n-4);
            d=mutil(b,c);
            printf("%lld\n",d.m[1][1]);
        }
    }
}



猜你喜欢

转载自blog.csdn.net/sinat_37668729/article/details/80103488