2018暑假杭电多校第七场

GuGuFishtion (hdu 6390 莫比乌斯反演)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6390

Sequence(hdu 6395 分段矩阵快速幂)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6395

比赛完之后再看这道题,其实也没有什么。。。
这道题最关键的就是怎么快速的分段
其实这也是非常常见的手法,在莫比乌斯反演的裸题以及杜教筛什么的都有:
就是在 [ i , x x / i ] 这段区间内, x i 的值是一样的,而且只有 s q r t ( x ) ,我觉得这也是杜教筛能够做到 O ( n 3 2 ) 的原因吧

#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const int MOD=1e9+7;
struct Matrix
{
    int n;
    LL a[3][3];
    Matrix (int n):n(n)
    {
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)a[i][j]=0;
    }

};
Matrix operator*(Matrix A,Matrix B)
{
    int n=A.n;
    Matrix res(n);
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    for(int k=0;k<n;k++)
    {
        res.a[i][j]+=A.a[i][k]*B.a[k][j];
        res.a[i][j]%=MOD;
    }
    return res;
}
Matrix operator^(Matrix A,int n)
{
    Matrix res(A.n),base=A;
    for(int i=0;i<A.n;i++)res.a[i][i]=1;
    while(n>0)
    {
        if(n&1)res=res*base;
        base=base*base;
        n>>=1;
    }
    return res;
}
int main()
{

    int T;
    cin>>T;
    LL A,B,C,D,P,N;
    LL Fn,Fn_1,FF,fn_1,fn_2,ff;
    while(T--)
    {
        cin>>A>>B>>C>>D>>P>>N;
        Matrix BASE(3);
        BASE.a[0][0]=D;
        BASE.a[0][1]=C;
        BASE.a[0][2]=BASE.a[1][0]=BASE.a[2][2]=1;
        Fn=B,Fn_1=A;
        if(N==1)cout<<A<<endl;
        else if(N==2)cout<<B<<endl;
        else 
        {
            for(int i=3,j;i<=N;i=j+1)
            {
                j=P/i==0?N:min(N,P/(P/i));  //这个就是关键的那句,[i,j]这一段区间的值是一样的 
                fn_1=Fn;
                fn_2=Fn_1;
                ff=P/i;
                Matrix base=BASE;
                base=base^(j-i+1);
                Fn=base.a[0][0]*fn_1%MOD+base.a[0][1]*fn_2%MOD+base.a[0][2]*ff%MOD;
                Fn_1=base.a[1][0]*fn_1%MOD+base.a[1][1]*fn_2%MOD+base.a[1][2]*ff%MOD;
            }
            cout<<Fn%MOD<<endl;
        }
    }
}

Swordsman(hdu 6396)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6396
题意:就是说有 n 个怪,最多有 5 种属性,自己也有 5 种属性,要在自己的每种属性都大于怪的每种属性的时候,就阔以把怪杀死,并且自己的属性还会得到对应的提升
问:最多能杀多少怪,以及最后自己的每个属性的值是多少?

参考博客:昨天看的今天写的。。。然后就没找到这位童鞋的博客T_T

这道题我参考的这位童鞋的思路感觉非常好懂:
就是先把每个属性从小到大排序,把比自己小的属性先记录下来,用一个 s u m [ i ] 表示第 i 个怪物记录了多少属性,然后在看如果某个怪物的 s u m 达到了 K 个,那么就把这个怪物吃了就行了

然后这道题还非要输入挂,于是又从那位童鞋那里得到了一个优秀的输入挂
原来以前的 getchar 那种挂是假的挂啊,,,我才知道

#include"bits/stdc++.h"
#define out(x) cout<<#x<<"="<<x
#define C(n,m) ((long long)fac[(n)]*inv[(m)]%MOD*inv[(n)-(m)]%MOD)
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
const int MOD=1e9+7;

//优秀的输入挂 
namespace fastIO {
    #define BUF_SIZE 100000
    //fread -> read
    bool IOerror = 0;
    inline char nc() {
        static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
        if(p1 == pend) {
            p1 = buf;
            pend = buf + fread(buf, 1, BUF_SIZE, stdin);
            if(pend == p1) {
                IOerror = 1;
                return -1;
            }
        }
        return *p1++;
    }
    inline bool blank(char ch) {
        return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
    }
    inline void read(int &x) {
        char ch;
        while(blank(ch = nc()));
        if(IOerror) return;
        for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
    }
    #undef BUF_SIZE
};
//using namespace fastIO;



int N,K;
struct AAA
{
    int v,id;
    bool operator<(const AAA &t)const
    {
        return v<t.v;
    }
};
AAA a[6][maxn],b[6][maxn];
int now[6];
int sum[maxn];
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        fastIO::read(N);
        fastIO::read(K);
        for(int i=1;i<=K;i++)fastIO::read(now[i]);
        for(int i=1;i<=N;i++)
        {
            sum[i]=0;
            for(int k=1;k<=K;k++)fastIO::read(a[k][i].v),a[k][i].id=i;
            for(int k=1;k<=K;k++)fastIO::read(b[k][i].v),b[k][i].id=i;
        }
        for(int i=1;i<=K;i++)sort(a[i]+1,a[i]+1+N);
        int pos[6]={1,1,1,1,1,1};//记录每次处理到哪里了 
        int cnt=0;
        while(1)
        {
            int flag=0;
            for(int i=1;i<=K;i++)
            {
                for(int j=pos[i];j<=N;j++)
                {
                    if(a[i][j].v<=now[i])
                    {
                        int id=a[i][j].id;
                        sum[id]++;
                        pos[i]++;
                        if(sum[id]==K)
                        {
                            for(int k=1;k<=K;k++)now[k]+=b[k][id].v;
                            cnt++;
                            flag=1;
                        }
                    }
                    else break;//不然就换下一个属性 
                }
            }
            if(flag==0)break;//找不到怪兽吃了 
        }
        printf("%d\n",cnt);
        for(int i=1;i<K;i++)printf("%d ",now[i]);
        printf("%d\n",now[K]);
    }
}

猜你喜欢

转载自blog.csdn.net/SwustLpf/article/details/81699163