數學考試5(test20170325)

【我的瘋狂被屠】(Crazy.pas/c/cpp Time:1s Memory:256M)

【問題描述】

我是一個傻×蒟蒻,總是被屠,最近連INDEX都開始屠我了,55555~
我研究了一下每天屠我的人的總數,發現這樣一個規律。
首先,每個人都只會屠我一次,然後就不屑於屠我了。第一天有1個人屠了我,第二天有1個人屠了我,但是從第三天開始,之前兩天屠我的人會告訴他們的一個朋友(當然是沒有屠過我的),讓他們來屠我。結果,從某時候起,居然連外星人都不遠千里來到地球開始屠我了。
作爲一個傻×蒟蒻真diaosi,我知道,如果一天被屠X次,則你的RP會上漲X2點。到今天爲止,我已經被屠了N 天。我想算一算這N天我獲得了多少點RP,但是我還得去選取數字,就拜託你了。勇敢的騷年啊快去創造奇蹟!

【輸入】

輸入文件名爲crazy.in。
輸入一行一個正整數N,表示我已經被屠天數。

【輸出】

輸出文件名爲crazy.out。
輸出一行一個整數,代表我獲得的RP量,因爲數字過大,所以對1000000007 取模。

【輸入輸出樣例】
crazy.in
4
crazy.out
15

【樣例解釋】
第一天被屠1次,第二天被屠1次,第三天被屠2次,第四天被屠3次。總計Rp值爲1+1+4+9=15

【數據範圍】

對於20%的數據,保證有1n20
對於50%的數據,保證有1n105
對於100%的數據,保證有1n1015

【題解】

真的被屠了。。。

其實很easy的發現就是有關斐波那契數列的問題

我們可以打表繼續發現就是:ni=1Fib2(n)=Fib(n)×Fib(n+1)

那麼只要用矩陣O(logN) 求解。

【代碼】
矩陣版

#include <cstdio>
#include <cstring>

#define Rep(i,s,t)  for(int i=s;i<=t;i++)

using namespace std;

typedef long long LL;

LL n,MOD=1000000007;

struct Mat{
    LL m[2][2];
};

Mat I={
    1,1,
    1,0,
};

Mat A={
    1,0,
    0,0,
};

Mat mul(Mat a,Mat b)
{
    Mat c;
    memset(c.m,0,sizeof c.m);
    Rep(i,0,1)  Rep(j,0,1)  Rep(k,0,1)
        c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%MOD;
    return c;
}

Mat pow(Mat a,LL b)
{
    Mat ans=a,p=I;
    while(b)
    {
        if(b & 1)   ans=mul(ans,p);
        p=mul(p,p);
        b>>=1;
    }
    return ans;
}


int main()
{
    freopen("crazy.in","r",stdin);
    freopen("crazy.out","w",stdout);
    scanf("%lld",&n);
    Mat ans=pow(A,n);
    printf("%lld\n",(ans.m[0][0]*ans.m[0][1])%MOD);
    return 0;
}

非矩陣版

#include <cstdio>
#include <cstring>
typedef long long LL;
const int MOD = 1000000007;

LL n;
LL left,right;

void work(LL x);

int main() {
    freopen("crazy.in","r",stdin);
    freopen("crazy.out","w",stdout);
    scanf("%lld",&n);
    work(n+1);
    printf("%lld\n",left*right%MOD);
    return 0;
}

void work(LL x) {
    if(x==1) {
        left=1;right=0;return ;
    }
    if(x==2) {
        left=1;right=1;return ;
    }
    if(x&1) {
        work(x-1);
        left=(left+right)%MOD;right=((left-right)%MOD+MOD)%MOD;
        return ;
    }
    work(x/2);
    LL tmpl=left,tmpr=right;
    left=(tmpl*tmpl%MOD+2*tmpl%MOD*tmpr%MOD)%MOD;
    right=(tmpl*tmpl%MOD+tmpr*tmpr%MOD)%MOD;
}

【我的數字選取】(Lucky.pas/c/cpp Time:1s Memory:256M)

【問題描述】

黑了很多人今天來黑下自己。
其實每個數字都是有靈魂的。譬如說我,能被2整除的數字看起來都有點2,。能被4整除的數字不僅2還一臉死相。能被5整除的數字看起來昨天才哭過。能被7整除的數字,原來就是你把5弄哭的!好吧,蛋疼到這裏結束。
其實做數據是很累人的,不管你們信不信,反正我是信了。
每次其實我都想這麼出數據。首先決定我今天的幸運數字,然後再選定若干個悲劇數字,一個數字是幸運的定義爲能夠整除我今天的幸運數字而且不能夠整除那若干個悲劇數字,最後選定一個區間[L,R] ,將這個區間中所有的幸運的數字挑出來。我想知道,我究竟能挑出多少個幸運的數字?
Note:幸運的數字和我今天的幸運數字不是同一個東西。

【輸入】

輸入文件名爲Lucky.in。
第一行4個正整數LN、N、L、R,分別表示我今天的幸運數字、悲劇數字的個數、區間的左界、區間的右界。
第二行包含N個正整數,表示若干個悲劇數字。

【輸出】

輸出文件名爲Lucky.out。
輸出僅一行,即我能挑出的幸運的數字的個數。

【輸入輸出樣例】

Lucky.in
2 1 3 4
7

Lucky.out

1

【數據範圍】

對於30%的數據,保證有0n21LR105
對於100%的數據,保證有0n151LR1015 ,今天的幸運數字和悲劇數字均可用無符號32 位整型變量存下。

【題解】

ans =能被今天的幸運數字整除的數的個數-能被今天的幸運數字和至少一個悲劇數字整除的數的個數+能被今天的幸運數字和至少兩個悲劇數字整除的數的個數……
因爲悲劇數字的個數不超過15 ,所以可以搜索.

【代碼】

#include <cstdio>

typedef long long LL;
const int size = 20;

LL ln,n,l,r;
LL cse[size],num[size],ans,tmp;

LL gcd(LL x,LL y);
void dfs(LL x);

int main() {
    freopen("lucky.in","r",stdin);
    freopen("lucky.out","w",stdout);
    scanf("%lld%lld%lld%lld",&ln,&n,&l,&r);
    for(LL i=1;i<=n;i++)
    scanf("%lld",&num[i]);
    dfs(1);
    printf("%lld\n",ans);
    return 0;
}

LL gcd(LL x,LL y) {
    return y==0 ? x : gcd(y,x%y);
}

void dfs(LL x) {
    if(x==n+1) {
    LL ret = ln;
    for(LL i=1;i<=tmp;i++) {
        ret = ret/gcd(ret,cse[i])*cse[i];
        if(ret>r or ret<0) return ;
    }
    if(tmp&1)
        ans-=r/ret-(l-1)/ret;
    else
        ans+=r/ret-(l-1)/ret;
    return ;
    }
    dfs(x+1);cse[++tmp]=num[x];
    dfs(x+1);tmp--;
}

【我的餵養計劃】(Feed.pas/c/cpp Time:1s Memory:256M)

【問題描述】

衆所周知,一中2011屆信息組有許多胖子。
無奈他們體型過於巨大,於是,他們就請我來節制他們的飲食。我決定,每天喂他們吃粥,這樣既可以保證營養,又可以減肥。但是,粥一旦多了,他們就覺得不爽,覺得自己長胖了,粥一旦少了,就不能讓他們該題目和考試了。經過長期觀察研究,最適合的粥量爲N,多一分不行,少一分不幹。
悲劇的是,我只有兩個勺子,而且它們的容量分別爲A和B!(這是感嘆號)當然,裝粥的那口缸和盛着剛做好的粥的鍋是非常大的,你可以將它們的容量視爲無窮大。每次,我只能使用一個勺子,用鍋裏的粥將這個勺子裝滿,然後倒入缸裏面,或者用缸裏面的粥將這個勺子倒滿,然後放回鍋裏。對了,每天鍋裏的粥可以視爲無窮大。我比較怕麻煩,希望知道一個最小的操作次數。
當然,他們要我節制他們若干天,所以每天的最適合粥量可能不同。但是,勺子是不會換的(囧)。

【輸入】

輸入文件名爲Feed.in。
輸入第一行爲兩個正整數A和B,分別表示兩個勺子的容量。
接下來若干行,每行一個正整數,代表某一天的最適合粥量。

【輸出】

輸出文件名爲Feed.out。
輸出若干行,對應於輸入中某一最適合粥量的最小操作次數。如果不能剛好達到最適合粥量,那麼輸出“BeiJu!”,不含引號。

【輸入輸出樣例】

Feed.in
2 4
3
2

Feed.out

BeiJu!
1

【數據範圍】

對於50%的數據,保證有1A,B,N105 ,數據組數等於1。
對於100%的數據,保證有1A,B,N109 ,數據組數不超過1000。

【題解】

題目要求的即爲滿足Ax+By=N 的使 |x|+|y| 最小的整數 x ,y .

用擴展gcd就可以求出特殊解,然後再求出通解。

分以下幾種情況分析
這裏寫圖片描述
【代碼】

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;

const LL INF = 9223372036854775807LL;
LL a,b,ta,tb,x,y,G,n,ans;

LL ex_gcd(LL a,LL b,LL &x,LL &y);

int main() {
    freopen("feed.in","r",stdin);
    freopen("feed.out","w",stdout);
    scanf("%lld%lld",&a,&b);
    G=ex_gcd(a,b,x,y);
    ta=a/G;tb=b/G;
    while(~scanf("%lld",&n)) {
        if(n%G!=0){
            puts("BeiJu!");
            continue;
        }
        ans=INF;
        LL x0=x*(n/G),y0=y*(n/G),rx,ry;

        rx=x0%tb;ry=y0+ta*(x0/tb);
        ans=min(abs(rx)+abs(ry),ans);

        rx-=tb;ry+=ta;
        ans=min(abs(rx)+abs(ry),ans);

        ry=y0%ta;rx=x0+tb*(y0/ta);
        ans=min(abs(rx)+abs(ry),ans);

        ry-=ta;rx+=tb;
        ans=min(abs(rx)+abs(ry),ans);

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

LL ex_gcd(LL a,LL b,LL &x,LL &y) {
    if(b==0) {
        x=1;y=0;
        return a;
    }
    LL ret=ex_gcd(b,a%b,y,x);
    y-=(a/b)*x;
    return ret;
}

總結

論考試不開long long 的後果: 100分直接掉20分。。。

而且打暴力越來越水了。。。

發佈了39 篇原創文章 · 獲贊 7 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章