1. 程式人生 > >致——世界上最幸福的女孩——Chtholly

致——世界上最幸福的女孩——Chtholly

Chtholly がんばれ

珂朵莉くとり,がんばれ
Are you going to Scarborough Fair?
Parsley, sage, rosemary, and thyme.
Remember me to one who lives there,
這裡寫圖片描述
She once was the true love of mine.
Tell her to make me a cambric shirt.
Parsley, sage, rosemary, and thyme.
Without no seams nor needlework.
Then she’ll be a true love of mine.
Tell her to find me an acre of land.
Parsley, sage, rosemary, and thyme.
這裡寫圖片描述


Between the salt water and the sea strand.
Then she’ll be a true love of mine.
Tell her to reap it in a sickle of leather.
Parsley, sage, rosemary, and thyme.
And gather it all in a bunch of heather.
Then she’ll be a true love of mine.
這裡寫圖片描述
Are you going to Scarborough Fair?
Parsley, sage, rosemary, and thyme.
Remember me to one who lives there,
She once was the true love of mine.*

在人類世界毀滅之後的“末日。
500年前,人類製造出的<17獸>失控,將人類毀滅,其他大多種族在“大賢者”的幫助下逃到了浮空島上。
而在人類製造出災禍之前,曾有“天災”和“星神”出現,以毀滅人類為代價保護這片土地,卻被人類的勇者阻止,而縱使擁有如此強大的戰力,卻在獸出現後無能無力,幾天後便慘遭滅亡。
500年後,浮空島上的居民已經有了一定的自衛能力,同時向地面進發,尋找資源,同時發現了之前與星神戰役中存活了最後一個人類,準勇者威廉·克梅修(在討伐“天災”黑燭公的戰役中遭到禁咒反噬石化而存活)
這裡寫圖片描述
在接受任務時受好友推薦進入妖精倉庫擔任軍方管理員,邂逅了珂朵莉和妖精一族。

威廉,500年後不再有家人,甚至是相同的人類,一個人想著曾經的生活,還記得女兒曾對他說過:一定要回來啊!500年後,自己終於歸來,迎接他的人卻早已不在。
珂朵莉,由星神艾露可的靈魂創造,在他人看來,她出現的意義就是為了保護浮空島,而自己堅信這一點,對死亡沒有一絲恐懼。縱使如此,在她坦然說出:如果四天後我就會死。這句話後,仍然希望能被威廉記住。
威廉,或許因為這份孤獨,才讓他更快融入妖精集體當中,讓他為這個種族付出自己的一切,讓他能在最後說出那句話:開什麼玩笑,至少,一定要救下這傢伙。
珂朵莉,抱歉,我已經沒有辦法獲得幸福了,因為我已經注意到了,我 已經 早就被幸福包圍了。
這裡寫圖片描述

珂朵莉:

我曾發誓要一直和他在一起

可以這樣發誓讓我無比幸福

我曾經覺得自己非常喜歡這個人

可以有這樣的感受讓我很幸福

他曾經對我說我一定會讓你幸福

能聽到他這樣說讓我很幸福

從他那裡得到這麼多的幸福

所以現在的我一定

不管別人如何說

一定是這個世界上最幸福的女孩**
這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

浮游大陸的68號島

一道使學傻了的人覺醒的好題(比如我)
一看區間查詢就想到線段樹,於是我就想分塊去做
再看查詢方式,預處理就超時了,於是最初一臉不可做的棄掉了這個題
之後想做一些有關讓自己感動過的番,漫畫,或者小說專題的東西。
於是又開始填這個坑,不過很遺憾,現在還要再留一個T3的坑
因為實在是不會,只能先隨便扒一個程式碼扔上來了

因為在一條線段上,所以我們可以先想到處理一個距離的字首和dis[i]
查詢的要求是一段區間移到一個點上
於是我們只要知道每個點的物品重量和距目標點的距離,就能求出
但顯然,100%的資料會超時
我們再處理一個重量的字首和w[i]
這樣再處理出到每一個點為止,前面所有物品移到0點的消耗cost[i]
查詢時,如果目標點在區間的左邊
我們用到右端點的總消耗 - 左端點消耗 cost[r] - cost[l]這樣是區間點全部移到
0點的消耗,只要再減去多移的一部分就好了,
區間重量減去多移的距離(w[r] - w[l])* dis[goal]
但我想不出怎麼只用cost來求位於區間右邊的情況
於是又開一個last反向處理一個cost,這樣用last代替cost同樣道理處理區間右邊的點
位於中間,就可以看做左區間和右區間來相同處理了
唯一注意的一點就是不要把目標點處理兩遍
!!!!最想說的就是,別忘了%,減了就要%,反正錯不了

#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
const ll mod = 19260817;
const int maxn = 200000 + 50 ;
ll dis[maxn],w[maxn],cost[maxn],last[maxn];//字首和的那些
ll n,m;
ll x;
long long ask(ll goal , ll l ,ll r){
    long long ans = 0;
    if(goal < l)
        ans = ((cost[r] - cost[l-1] + mod)%mod - ((w[r] - w[l-1]+mod)%mod * dis[goal]+mod)%mod+mod)%mod;
    else if(goal > r)
        ans = ((last[l] - last[r+1] + mod)%mod - (w[r] - w[l-1] + mod)%mod * (dis[n] - dis[goal] + mod)%mod+mod)%mod;
    else{
        ans += ((cost[r] - cost[goal-1] + mod)%mod - (w[r] - w[goal-1]+mod)%mod * dis[goal]+mod)%mod;
        ans += ((last[l] - last[goal] + mod)%mod - (w[goal-1] - w[l-1]+mod)%mod * (dis[n] - dis[goal]+mod)%mod+mod)%mod;
    }
    return (ans + mod)%mod;
}
int main(){
    scanf("%lld%lld",&n,&m);ll l, r;
    for(ll i = 2 ; i <= n ; i ++){
        scanf("%lld",&x);//long long , scanf讀入別忘了lld
        x %= mod;
        dis[i] = (dis[i-1] + x)%mod;
    }
    for(ll i = 1 ; i <= n ; i ++){
        scanf("%lld",&x);
        x %= mod;
        w[i] = (w[i-1] + x)%mod;
        cost[i] = (cost[i-1] + x * dis[i])%mod;
    }
    for(ll i = n - 1 ; i > 0 ; i --)
        last[i] = (last[i+1] + (w[i] - w[i-1]+mod)%mod * (dis[n] - dis[i] + mod)%mod)%mod;
    for(int i = 1 ; i <= m ; i ++){
        scanf("%lld%lld%lld",&x,&l,&r);
        printf("%lld\n",ask(x,l,r));
    }
    return 0;
}

Chtholly Nota Seniorious

當時認為唯一可做的題
讀題就可以看出是一個二分(較大的最小值),起碼現階段是這樣
二分答案(最小極差)因為有了不能轉兩次彎的限制,所以相對好做了(或許吧)
從第一個點開始,一個點一個點的跑,維護一個最大值maxn,一個最小值minn
如果當前的點加入不會使極差超過當前的答案,標記這個點done[i]
否則停下,將當前點的列數標記limit,下面每一行不能超過這個限制
遍歷完後,處理未標記的點的最大值和最小值,求極差
大於答案 l = mid + 1 , 否則 r = mid。
但有情況會出錯
例如
5 5
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
5 5 1 1 1
5 5 5 5 5
5 5
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 5 5 5
5 5 5 5 5
這樣的話,limit會受到影響而導致後面可以連成塊的點並不會跑
較為簡單的處理方法就是複製一個映象的圖,這樣檢測兩個圖,就可以解決

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 2000 + 50;
int a[maxn][maxn],b[maxn][maxn],n,m;
bool done[maxn][maxn];
bool check(int mid){
    memset(done,0,sizeof(done));
    int limit = m + 1;
    int maxn = a[1][1] , minn = a[1][1];
    for(int i = 1 ;  i <= n ; i ++)
        for(int j = 1 ; j < limit ; j ++){
            if(maxn - a[i][j] > mid || a[i][j] - minn > mid){
                limit = j;
            }
            else{
                if(a[i][j] > maxn)maxn = a[i][j];
                if(a[i][j] < minn)minn = a[i][j];
                done[i][j] = 1;
            }
        }
    maxn = 0 , minn = 1e9;
    for(int i = 1 ; i <= n ; i ++){
        for(int j = 1 ; j <= m ; j ++){
            if(!done[i][j]){
                if(a[i][j] > maxn) maxn = a[i][j];
                if(a[i][j] < minn) minn = a[i][j];
                if(maxn - minn > mid)return false;
            }
        }   
    }
    return true;
}
bool check_t(int mid){
    memset(done,0,sizeof(done));
    int limit = m + 1;
    int maxn = b[1][1] , minn = b[1][1];
    for(int i = 1 ;  i <= n ; i ++)
        for(int j = 1 ; j < limit ; j ++){
            if(maxn - b[i][j] > mid || b[i][j] - minn > mid){
                limit = j;
            }
            else{
                if(b[i][j] > maxn)maxn = b[i][j];
                if(b[i][j] < minn)minn = b[i][j];
                done[i][j] = 1;
            }
        }
    maxn = 0 , minn = 1e9;
    for(int i = 1 ; i <= n ; i ++){
        for(int j = 1 ; j <= m ; j ++){
            if(!done[i][j]){
                if(b[i][j] > maxn) maxn = b[i][j];
                if(b[i][j] < minn) minn = b[i][j];
                if(maxn - minn > mid)return false;
            }
        }   
    }
    return true;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1 ; i <= n ; i ++){
        for(int j = 1 ; j <= m ; j ++){
            scanf("%d",&a[i][j]);
            b[i][m-j+1] = a[i][j];//複製映象,左右對稱即可
        }
    }
    int l = 0 , r = 1e9;
    while(l < r){
        int mid = (l + r)>>1;
        if(check(mid)||check_t(mid))
            r = mid;
        else l = mid + 1;
    }
    printf("%d",l);
}

T3之前我們先貼一個其他的東西

神奇的尤拉函式

這東西是真的強,順便證明一下費馬小定理
這裡寫圖片描述
n 和 a 是正整數,同時互質
將1~n中與n互質的數按順序排布:x1,x2……xφ(n) (顯然,共有φ(n)個數)
(φ(n))是從1到n為止,與n互質的數的個數
考慮這些:
m1=a*x1;m2=a*x2;m3=a*x3……mφ(n)=a*xφ(n)
因為a與n互質,x與n互質,所以m1……mn中任何兩個數都不可能%n同餘
其次,所有m/n後重新排列,同餘於x1,x2,x3,由上一點可知
也可以手推幾組資料(%n不同餘,同時n-1個)
這樣m1*m2*m3……mφ(n)≡x1*x2*x3……xφ(n) (mod n)
再這樣a^[φ(n)]*(x1*x2*x3……xφ(n))≡x1*x2*x3……xφ(n)
K{a^[φ(n)]-1}≡0 ( mod n ) 這裡K=x1*x2*x3……xφ(n)。
可知K{a^[φ(n)]-1}被n整除。但K中的因子x1,x2……都與n互質,所以K與n互質。那麼a^[φ(n)]-1必須能被n整除,即a^[φ(n)]-1≡0 (mod n),即a^[φ(n)]≡1 (mod n)
費馬小定理:
a是不能被質數p整除的正整數,則有a^(p-1) ≡ 1 (mod p)
p是質數,所以φ(p) = p-1,代入尤拉定理。推論:對於任意正整數a,有a^p-1 ≡ 1 (mod p),因為a能被p整除時結論顯然成立。

#include<iostream>
#include<cstdio>
using namespace std;
int s;
int eulur(int n){
    int res = n, a = n;
    for(int i = 2 ; i*i <= a ; i ++){
        if(a % i == 0){
            res = res/i*(i-1);
            while(a%i == 0)
                a/=i;
        }
    }
    if(a > 1)res = res / a * (a - 1);
    return res;
}
int main(){
    scanf("%d",&s);
    printf("%d",eulur(s));
}

畢竟是珂朵莉的應援,T3奈芙蓮就放到下一個吧

太陽の傾いたこの世界で -broken chronograph-
空の上の森の中の -late autumn night’s dream-
この戦いが終わったら -starry road to tomorrow-
帰らぬ者と、待ち続けた者たち -dice in pot-
誰も彼もが、正義の名のもとに -from dawn till dusk-
消えない過去、消えていく未來 -no news was good news-
ただいま帰りました -home, sweet home-
いずれその陽は落ちるとしても -slight light, slight hope-
たとえ未來が見えなくても -moonlit sorcery-
いまこの時の輝きを -my happiness-
どうか、忘れないで -evidence of existence-
世界で一番幸せな女の子 -CHTHOLLY-
這裡寫圖片描述

くとり

さいこう