【INDEX1】(Indexone.pas/c/cpp Time:1s Memory:256M)
【問題描述】
INDEX 是誰?兄弟,這個問題你如果不知道我就只能懷疑你是從火星來的了。 但是,如果你真的不知道他是誰,那麼,你可能和他擁有同一個故鄉。 其實當年 INDEX 在火星上有 N 個基友和 M 個妹子,生活真是非常逍遙。他每天都把 基友和妹子排成一隊,使得他能夠站在最前面,領着他的基友後宮團遊街(囧)。 但是,他的妹子們的嫉妒心是很強的,如果兩個妹子站在一起,肯定會爲 INDEX 吵得 不可開交。同時,INDEX 也是有老婆的人,他身後,也就是隊伍的第一個人必須是他的基 友後宮團的團長——他老婆(也就是說,M 個妹子中有一個是他的老婆,爲了使題目容易 理解,也就是第一個人已經確定是 M 個妹子中的一個了)。而且,他希望由一個基友來殿後。 現在 INDEX 想知道,他能夠排成多少種不同的隊伍,使得這個隊伍滿足他的要求?
【輸入】
輸入文件名爲 Indexone.in。 輸入一行包含兩個整數 N 和 M。
【輸出】
輸出文件名爲 Indexone.out。 輸出一行,表示合法的隊伍總數對
【輸入輸出樣例】
Indexone.in
1 1
Indexone.out
1
【數據範圍】
對於 30%的數據,保證有1≤N,M≤1000。
對於另外 30%的數據,保證有1≤M≤10。
對於 100%的數據,保證有1≤N,M≤1000000。
【題解】
這個題其實和那個什麼01序列差不多,答案:
【代碼】
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MOD = 1000000007;
const int size = 1000010;
LL a[size],b[size];
LL n,m,ans=1;
LL ksm(LL,LL,LL);
int main() {
freopen("indexone.in","r",stdin);
freopen("indexone.out","w",stdout);
scanf("%lld%lld",&n,&m);
if(m>n)
return puts("0"),0;
a[0]=1;
for(LL i=1;i<=n;i++)
a[i]=a[i-1]*i%MOD;
b[n]=ksm(a[n],MOD-2,MOD);
b[0]=1;
for(LL i=n-1;i>=1;i--)
b[i]=b[i+1]*(i+1)%MOD;
ans=a[n]*a[n-1]%MOD*b[n-m]%MOD;
printf("%lld\n",ans);
return 0;
}
LL ksm(LL x,LL y,LL Mod) {
x%=Mod;
LL ret=1;
while(y) {
if(y&1)
ret=ret*x%Mod;
x=x*x%Mod;
y>>=1;
}
return ret;
}
【INDEX2】(Indextwo.pas/c/cpp Time:1s Memory:256M)
【問題描述】
故事承接上文。 這事發生在博士還不那麼內涵,現哥還不那麼傻逼,姜嗲還沒開始玩 dota,巨胖才 50Kg 的時候。有一天,INDEX 的老婆再也不能忍受 INDEX 那過分龐大超過一阿伏伽德羅常數的 後宮量,那天夜裏,她將 INDEX 綁架到了飛船上,“私奔”到了月球,在《Fly me to the moon》 的歌聲中。好美啊! 這個時刻,INDEX 發現有一顆藍色的星球一直在繞着一顆紅色的星球轉動。接着,他 又發現,他的故鄉火星也一直在繞着這顆紅色的星球轉動!!!厲害爆了有木有!!!現在,他 的老婆將這顆藍色星球命名爲 A,他們的故鄉火星命名爲 B,並將他們的軌道平均分成 L 塊,形成了 L 塊扇形區域嗎,並從 0 到 L-1 逆時針標號,A 星球和 B 星球都是沿逆時針繞 紅色星球轉動。一開始的時間計算爲 0,在 0 時刻時,A 處在 Sa 塊,B 處在 Sb 塊。A 的移 動速度爲 Va 塊每 INDEX 小時,B 的移動速度爲 Vb 塊每 INDEX 小時。INDEX 向她老婆發 誓,他們會在月球上度過一段美好的二人時光,直到到某個 INDEX 小時整點的鐘聲敲響時, 若星球 A 和星球 B 所在塊的編號相同,那麼,他們啓程返回火星。 思念自己龐大後宮團的 INDEX 想問你,他們啓程返回火星的時刻。
【輸入】
輸入文件名爲 Indextwo.in。 輸入僅一行,包含五個正整數,分別爲 L,Sa,Sb,Va,Vb。
【輸出】
輸出文件名爲 Indextwo.out 輸出僅一行,表示他們啓程返回火星的時刻。若永遠都不存在那個時刻,請輸出 “Ohahahahahahaha”,不包含雙引號。
【輸入輸出樣例】
Indextwo.in
3 1 1 2 2
Indextwo.out
0
【數據範圍】
對於 30%的數據,保證有 1≤L≤100。
對於 100%的數據,保證有 1≤L≤1000000,而且 0≤Sa,Sb≤L-1,1≤Va,Vb≤L。
【題解】
我們可以發現問題可以轉化爲求
可以轉化爲
此時可以很明顯發現用擴展gcd就可以求出一個解,那麼求通解就很簡單了。而我們只要當中的最小整數解。
【代碼】
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
LL l,sa,sb,va,vb;
LL x,y;
void swap(int &a,int &b) {
a^=b;b^=a;a^=b;
}
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-=x*(a/b);
return ret;
}
int main(){
freopen("indextwo.in","r",stdin);
freopen("indextwo.out","w",stdout);
scanf("%lld%lld%lld%lld%lld",&l,&sa,&sb,&va,&vb);
if(va<vb) {
swap(va,vb);
swap(sa,sb);
}
if(sa==sb)
return puts("0"),0;
LL Gcd=ex_gcd(va-vb,l,x,y);
if((sb-sa)%Gcd!=0)
return puts("Ohahahahahahaha"),0;
LL bd=l/Gcd;
x*=((sb-sa)/Gcd);
x=(x%bd+bd)%bd;
printf("%lld\n",x);
return 0;
}
【INDEX3】(Indexthree.pas/c/cpp Time:1s Memory:256M)
【問題描述】
故事承接上文。 INDEX 回家之後,果斷廢棄了他的後宮基友團。開始和他老婆移居到農村,在一個 N 行 M 列的土地上,在平面直角座標系中,就是橫座標從 1 到 N,縱座標從 1 到 M 的地方上 種植樹木。特別的,在原點那裏,有一個 INDEX 造的太陽。然而,這次種植的樹木名字叫 做超能樹,爲啥叫超能呢,因爲它超需要能量,所以叫做超能樹,如果這棵樹無法從 INDEX 造的太陽中獲得能量,也就是有其它樹擋住了它的陽光,它就會死去。一棵樹擋住了另一棵 樹當且僅當這兩棵樹與原點三點共線,且一棵樹距離原點更近。INDEX 已經種植了在他的 土地上的每個整點上都種植了一棵超能樹。INDEX 想知道,有多少樹可以活下來?
【輸入】
輸入文件名爲 Indexthree.in。 輸入僅一行,包含兩個正整數 N 和 M。
【輸出】
輸出文件名爲 Indexthree.out。 輸出僅一行,表示最後活下來的樹木個數。
【輸入輸出樣例】
Indexthree.in
2 2
Indexthree.out
3
【樣例解釋】
(2,2)上的樹被(1,1)上的樹擋住了,所以只有兩棵樹成活。
【數據範圍】
對於 60%的數據,保證有 1≤N,M≤1000。
另外 20%的數據,保證 N=M。
對於 100%的數據,保證有 1≤N,M≤1000000。
【題解】
易知,(x,y) 上的樹不被其它樹擋住的充要條件是gcd(x,y)=1。
因爲若gcd(x,y)=d,d>1,那麼 (x,y) 上的樹必會被(x/d,y/d) (注:不知爲何公式gg了)上的樹擋住。
所以,問題轉化爲:對於給定的整數 a , b,有多少正整數對 (x,y),滿足x≤a,y≤b,並且gcd(x,y)=1。
前60分,直接gcd(i,j)==1判斷即可(暴力分真多)
後20分,用歐拉函數搞一下就可以了。
最後20分,據說要莫比烏斯反演。(然而並不會)
【代碼】
先給上蒟蒻的60分暴力代碼
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
LL gcd(LL a,LL b) {
return b?gcd(b,a%b):a;
}
LL n,m,ans=0;
int main() {
freopen("indexthree.in","r",stdin);
freopen("indexthree.out","w",stdout);
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
if(gcd(i,j)==1)
ans++;
}
}
printf("%lld\n",ans);
return 0;
}
總結
這次考試竟然沒有炸,真的神啦,會做的竟然沒有炸,太神了!!!