2018.10.10考試
一次涼涼的考試
T110078. 「一本通 3.2 練習 4」新年好
題目描述
原題來自:CQOI 2005
重慶城裏有 \(n\) 個車站,\(m\) 條雙向公路連接其中的某些車站。每兩個車站最多用一條公路連接,從任何一個車站出發都可以經過一條或者多條公路到達其他車站,但不同的路徑需要花費的時間可能不同。在一條路徑上花費的時間等於路徑上所有公路需要的時間之和。
佳佳的家在車站 \(1\),他有五個親戚,分別住在車站 \(a\),\(b\),\(c\),\(d\),\(e\)。過年了,他需要從自己的家出發,拜訪每個親戚(順序任意),給他們送去節日的祝福。怎樣走,才需要最少的時間?
輸入格式
第一行:\(n\)
第二行:\(a\),\(b\),\(c\),\(d\),\(e\) 為五個親戚所在車站編號。
以下 \(m\) 行,每行三個整數 \(x\),\(y\),\(t\),為公路連接的兩個車站編號和時間。
輸出格式
輸出僅一行,包含一個整數 \(T\),為最少的總時間。
樣例
樣例輸入
6 6
2 3 4 5 6
1 2 8
2 3 3
3 4 4
4 5 5
5 6 2
1 6 7
樣例輸出
21
數據範圍與提示
對於全部數據,\(1≤n≤50000\),\(1≤m≤10^5\),\(1<a,b,c,d,e≤n\),\(1≤x,y≤n\),\(1≤t≤100\)
正解沒想出來,就寫了\(n^3\)
正解是求點1和五個親戚的點到所有點的最短路,然後dfs求怎樣排序最優
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #define inf 0x7ffffff using namespace std; const int N=50005; struct node { int to,nxt,w; }e[N<<2]; int head[N],tot=0,a[10]; int dt[50]; int dis[7][N],vis[N],vis2[N]; int n,m,ans=inf; void add(int x,int y,int z) { e[++tot]=(node){y,head[x],z}; head[x]=tot; } void spfa(int s,int k) { queue<int>q; memset(vis2,0,sizeof(vis2)); q.push(s); vis2[s]=1; dis[k][s]=0; while(!q.empty()) { int u=q.front(); q.pop(); vis2[u]=0; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(dis[k][v]>dis[k][u]+e[i].w) { dis[k][v]=dis[k][u]+e[i].w; if(!vis2[v]) { vis2[v]=1; q.push(v); } } } } } void dfs(int k) { if(k==6) { int s=0; for(int i=1;i<6;i++) s+=dis[dt[i]][a[dt[i+1]]]; ans=min(ans,s); return; } for(int i=2;i<=6;i++) { if(!vis[i]) { vis[i]=1; dt[k+1]=i; dfs(k+1); vis[i]=0; } } } int main() { scanf("%d%d",&n,&m); for(int i=2;i<=6;i++) scanf("%d",&a[i]); for(int i=1;i<=m;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); add(a,b,c); add(b,a,c); } memset(dis,0x3f,sizeof(dis)); a[1]=1; dt[1]=1; for(int i=1;i<=6;i++) spfa(a[i],i); dfs(1); printf("%d",ans); return 0; }
T210178. 「一本通 5.5 例 4」旅行問題
題目描述
原題來自:POI 2004
John 打算駕駛一輛汽車周遊一個環形公路。公路上總共有 n 車站,每站都有若幹升汽油(有的站可能油量為零),每升油可以讓汽車行駛一千米。John 必須從某個車站出發,一直按順時針(或逆時針)方向走遍所有的車站,並回到起點。在一開始的時候,汽車內油量為零,John 每到一個車站就把該站所有的油都帶上(起點站亦是如此),行駛過程中不能出現沒有油的情況。
任務:判斷以每個車站為起點能否按條件成功周遊一周。
輸入格式
第一行是一個整數 \(n\),表示環形公路上的車站數;
接下來 \(n\) 行,每行兩個整數 \(p_i\),\(d_i\),分別表示表示第 \(i\) 號車站的存油量和第 \(i\) 號車站到下一站的距離。
輸出格式
輸出共 \(n\) 行,如果從第 \(i\) 號車站出發,一直按順時針(或逆時針)方向行駛,能夠成功周遊一圈,則在第 \(i\) 行輸出 TAK,否則輸出 NIE。
樣例
樣例輸入
5
3 1
1 2
5 2
0 1
5 4
樣例輸出
TAK
NIE
TAK
NIE
TAK
數據範圍與提示
對於全部數據 \(3≤n≤10^6\),\(0≤p_i≤2×10^9\),\(0<d_i≤2×10^9\).
這個題開始看。。。不會,寫暴力,\(n^2\),不知道考試為啥腦殘的把\(d_i\)認為是點i到i-1和i+1,的距離,繼續涼涼,不知道為啥還有10分
正解單調隊列
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int N=2e6+1;
int n,a[N],head,tail,pq[N],last;
long long q[N],p[N],qz[N];
bool ans[N];
void work1()
{
for(int i=1;i<=2*n-1;i++)
qz[i]=qz[i-1]+a[i];
head=1;tail=0;
for(int i=1;i<=2*n-1;i++)
{
while(head<=tail&&q[tail]>=qz[i]) tail--;
q[++tail]=qz[i];
p[tail]=i;
while(head<=tail&&i-p[head]>=n) head++;
if(i>=n)
{
if(q[head]>=qz[i-n])
ans[i-n+1]=1;
}
}
return ;
}
void work2()
{
qz[1]=pq[1];
for(int i=2;i<=n+1;i++)
qz[i]=qz[i-1]+pq[n-i+2];
for(int i=n+2;i<=n*2-1;i++)
qz[i]=qz[i-1]+pq[n*2-i+2];
head=1;tail=0;
for(int i=1;i<=2*n-1;i++)
{
while(head<=tail&&q[tail]>=qz[i]) tail--;
q[++tail]=qz[i];
p[tail]=i;
while(head<=tail&&i-p[head]>=n) head++;
if(i>=n)
{
if(q[head]>=qz[i-n])
{
if(i==n) ans[1]=1;
else ans[2*n-i+1]=1;
}
}
}
return ;
}
int main()
{
scanf("%d",&n);
for(int i=1,u,v;i<=n;i++)
{
scanf("%d%d",&u,&v);
a[i+n]=a[i]=u-v;
pq[i+n]=pq[i]=u-last;
last=v;
}
pq[1]-=last;
pq[1+n]=pq[1];
work1();
work2();
for(int i=1;i<=n;i++)
{
if(ans[i])puts("TAK");
else puts("NIE");
}
return 0;
}
T310220. 「一本通 6.5 例 2」Fibonacci 第 n 項
題目描述
大家都知道 Fibonacci 數列吧,\(f_1=1\),\(f_2=1\),\(f_3=2\),\(f_4=3\),??,\(f_n=f_{n?1}+f_{n?2}\)。
現在問題很簡單,輸入 \(n\) 和 \(m\),求 \(fn?mod?m\)。
輸入格式
輸入 \(n\),\(m\)。
輸出格式
輸出 \(f_n?mod?m\)。
樣例
樣例輸入
5 1000
樣例輸出
5
數據範圍與提示
對於 100%100%100% 的數據, \(1≤n≤2×10^9\),\(1≤m≤10^9+10\)
唯一沒有出錯的題.....
矩陣快速冪板子
#include<iostream>
#include<cstdio>
#include<cstring>
#define int long long
using namespace std;
int mod;
struct node
{
int a[2][2];
}ss,ans;
node mul(node &a,node &b)
{
node c;
for(int i=0;i<2;++i)
for(int j=0;j<2;++j)
{
c.a[i][j]=0;
for(int k=0;k<2;++k)
c.a[i][j]=(c.a[i][j]+(a.a[i][k]*b.a[k][j])%mod)%mod;
}
return c;
}
void fpow(int b)
{
while(b)
{
if(b&1)ans=mul(ans,ss);
ss=mul(ss,ss);
b>>=1;
}
}
signed main()
{
int n;
scanf("%lld%lld",&n,&mod);
ans.a[0][0]=ans.a[1][0]=1;
ans.a[0][1]=ans.a[1][1]=0;
ss.a[0][0]=ss.a[1][0]=ss.a[0][1]=1;
ss.a[1][1]=0;
fpow(n-1);
printf("%lld",ans.a[0][0]);
return 0;
}
2018.10.10考試