我的涨分日记(四)——BestCoder Round #80

好久没有打BestCoder了(其实一直都在打,不过涨涨跌跌,就没高兴写题解),昨天做了一波,竟然都是我最喜欢的数学题。当然做得不错,成功上了1900,虽然有点运气的成分。


第一题 hdu-5665

分析:首先一点,写得快的人第一次交都PE了(我也是),出题人说数据没问题,最后也不了了之了(吐槽免不了)。打比赛的时候好多人对自然数的定义有异议,不知道0算不算自然数,我记得小学就学了0算自然数(0怎么不自然了=。=)。这道题算简单的把,毕竟第一题。就是判断一下,这些数集里面有没有0和1,0不用说,没有任何数相加可以得到0的,除了0,所以0必须要有。然后对于1,当然也没有数相加可以得到1,除了1自身,所以1必须要有。但是既然有了1的话其他所有自然数都可以得到了,那么只需要判断一下0和1是否存在于数集即可。

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <fstream>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define clr(x,y) memset(x,y,sizeof(x))
#define rep(i,n) for(int i=0;i<(n);i++)
#define repf(i,a,b) for(int i=(a);i<=(b);i++)
#define maxn 1000000+5
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define IT iterator
#define push_back PB

typedef long long ll;
const double eps = 1e-10;
const double pi  = acos(-1);
const ll mod = 1e9+7; 
const int inf = 0x3f3f3f3f;


int main()
{
    //freopen("d:\\acm\\in.in","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {

        int n,a;
        int k=0,h=0;
        scanf("%d",&n);
        while(n--)
        {
            scanf("%d",&a);
            if(a==0)k=1;
            if(a==1)h=1;
        }
        if(k&&h)puts("YES");
        else puts("NO");
    }
    return 0;
}




第二题 hdu-5666

分析:第二题是我最想吐槽的一道题,出题人语文水平真心有问题,我看了半天一点没看懂(=。=)。最后还是对亏了Acfun的大神,无意中透露一点信息,我才知道原来题目是唬人的。虽然连了那么多线段,但是因为P是质数,所以不可能有任何整点在后来连起来的线段上,结论就是完全不用看这些,直接1+2+3+......+(p-2),当然是等差数列求和公式,唯一的坑点就是两个long long相乘爆掉把,好多小朋友非常可惜的被hack了(我也hack了两个)。我只能说这回学到了把,有个神奇的东西叫快速幂加法,虽然并没有变的很快,但是两个longlong相乘取模不会爆longlong。

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <fstream>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define clr(x,y) memset(x,y,sizeof(x))
#define rep(i,n) for(int i=0;i<(n);i++)
#define repf(i,a,b) for(int i=(a);i<=(b);i++)
#define maxn 1000000+5
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define IT iterator
#define push_back PB

typedef long long ll;
const double eps = 1e-10;
const double pi  = acos(-1);
const ll mod = 1e9+7; 
const int inf = 0x3f3f3f3f;

ll p;
ll mul(ll a,ll b)
{
    ll ans=0;
    while(b)
    {
        if(b&1)ans=(ans+a)%p;
        a=(a+a)%p;
        b>>=1;
    }
    return ans;
}
int main()
{
    //freopen("d:\\acm\\in.in","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll q;
        scanf("%I64d %I64d",&q,&p);
        if(q==2)
        {
            puts("0");
            continue;
        }
        ll ans=mul((q-1)/2,(q-2));
        printf("%I64d\n",ans);
    }
    return 0;
}




第三题 hdu-5667

分析:最近刚刷完矩阵快速幂专题,要是这道题都不会的话,也是真的醉了。稍微写上几个f(n),很显然的看到了递推式主要体现在了指数上,那么不用管a^b,只要先求指数,然后再来一遍整数快速幂即可。考虑,不妨设一个新的数列G(n),G(1)=0,G(2)=1,G(n)=c*G(n-1)+G(n-2)+1。看过我前一个专题的人,应该很简单的就可以构造出矩阵。


注意:这里面有个坑点,对于矩阵内部取模的话,是不可以用p的(p是对底数取模,而不是指数,这里求的是指数),根据费马小定理要用p-1。但是有一个问题,对于a%p==0的情况,那么底数显然是0,只要构造一个指数正好能被p-1整除的情况,就会意外的出现0的0次方的情况(其实数学上是不存在0的0次方的),最后结果是1,但是正确是0。对于这种情况只要特判一下就行了,对于求逆元都有这种情况啊。我的代码是非常猥琐的躲过的这个问题,我的矩阵结果最后一次是直接加的,没有取模(我不记得是忘了还是什么=。=),所以基本没有能够hack掉我的代码的数,虽然看上去不是标准答案啦。(这里贴我的代码了)

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <fstream>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define clr(x,y) memset(x,y,sizeof(x))
#define rep(i,n) for(int i=0;i<(n);i++)
#define repf(i,a,b) for(int i=(a);i<=(b);i++)
#define maxn 0+5
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define IT iterator
#define push_back PB

typedef long long ll;
const double eps = 1e-10;
const double pi  = acos(-1);
const ll mod = 1e9+7; 
const int inf = 0x3f3f3f3f;

ll p;
ll q;
ll low(ll a,ll n)
{
    ll ans=1;
    while(n)
    {
        if(n&1)ans=ans*a%p;
        a=a*a%p;
        n>>=1;
    }
    return ans;
}
struct matrix 
{
    int n;
    ll maze[maxn][maxn];
    void init(int n)
    {
        this->n=n;
        clr(maze,0);
    }
    matrix operator * (const matrix& rhs)
    {
        matrix ans;
        ans.init(n);
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                for(int k=0;k<n;k++)
                    ans.maze[i][j]=(ans.maze[i][j]+maze[i][k]*rhs.maze[k][j])%q;
        return ans;
    }
};
matrix qlow(matrix a,ll n)
{
    matrix ans;
    ans.init(a.n);
    for(int i=0;i<a.n;i++)ans.maze[i][i]=1;
    while(n)
    {
        if(n&1)ans=ans*a;
        a=a*a;
        n>>=1;
    }
    return ans;
}
int main()
{
    //freopen("d:\\acm\\in.in","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll n,a,b,c;
        scanf("%I64d %I64d %I64d %I64d %I64d",&n,&a,&b,&c,&p);
        ll ans=low(a,b);
        if(n<=2)
        {
            if(n==1)printf("%I64d\n",1%p);
            else printf("%I64d\n",ans);
            continue;
        }
        q=p-1;
        matrix ant;
        ant.init(3);
        ant.maze[0][0]=ant.maze[0][2]=ant.maze[1][2]=ant.maze[2][1]=1;
        ant.maze[2][2]=c;
        ant=qlow(ant,n-2);
        ans=low(ans,ant.maze[0][2]+ant.maze[2][2]);
        printf("%I64d\n",ans);
    }
    return 0;
}




第四题 hdu-5668

分析:很久很久以前学过同余方程组,不过很遗憾忘光了。=。=

贴一下学长的代码

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

using namespace std;

#define PB push_back
#define SIZE(x) (int)x.size()
#define clr(x,y) memset(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ALL(t) (t).begin(),(t).end()
#define FOR(i,n,m) for (int i = n; i <= m; i ++)
#define ROF(i,n,m) for (int i = n; i >= m; i --)
#define RI(x) scanf ("%d", &(x))
#define RII(x,y) RI(x),RI(y)
#define RIII(x,y,z) RI(x),RI(y),RI(z)

typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;

const ll mod = 1e9+7;
const ll LINF = 1e18;
const int INF = 1e9;
const double EPS = 1e-8;

/**************************************END************************************/



void ext_gcd(ll a,ll  b,ll &d,ll &x,ll &y)  
{  
    if(!b)  
    {  
        x=1;  
        y=0;  
        d=a;  
        return ;  
    }  
    else  
    {  
        ext_gcd(b,a%b,d,y,x);  
        y-=a/b*x;  
    }  
}  
vector<int> a, b;
ll solve()///x=b[i](mod a[i])  
{  
    ll ta=a[0],tb=b[0];  
    bool flag=true;  
    for(int i=1; i<SIZE (a); i++)  
    {  
        ll xa=ta,xb=a[i],c=b[i]-tb,d,x,y;  
        ext_gcd(xa,xb,d,x,y);  
        if(c%d)  
        {  
            flag=false;  
            break;  
        }  
        ll tmp=xb/d;  
        x=(x*(c/d)%tmp+tmp)%tmp;  
        tb=ta*x+tb;  
        ta=ta/d*a[i];  
    }  
    if(!flag) return -1;   
    return tb;  
}  

int main (){
    int T;
    cin >> T;
    while (T --){
        a.clear ();
        b.clear ();
        int n;
        cin >> n;
        vector<bool> vis(n);
        int now = -1;
    vector<int> vec(n+1);
    FOR (i, 1, n){
        int t;
        cin >> t;
        vec[t] = i;
    }
        ROF (i, n, 1){
            int cnt = 0;
            int t = vec[n-i+1];
            t --;
            while (now != t){
                now ++;
                if (now >= n){
                    now = 0;
                }
                if (!vis[now]){
                    cnt ++;
                }
            }
            vis[t] = true;
            a.PB (i);
            b.PB (cnt-1);
        }
//        FOR (i, 0, n-1){
//            cout << a[i] << " ";
//        }
//        cout << endl;
//        FOR (i, 0, n-1){
//            cout << b[i] << " ";
//        }
//        cout << endl;
        ll ans = solve () + 1;
        if (ans == 0){
            puts ("Creation August is a SB!");
        }else{
            cout << ans << endl;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值