我的漲分日記(四)——BestCoder Round #80

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/shengtao96/article/details/51172870

好久沒有打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;
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章