前言
過年在家頹廢很久之後終於開始嫌棄自己,開始認真了。
開始開專題並且補完CAMP的題解。
這是第一天的camp題解,賽中只做出BCFJ四個題。
賽後補完:ABCEFIJ
題解
A.機器人
題意
wls管理的倉庫分爲兩個區,這兩個區坐落在兩條平行的直線上,每個區有個站點,標號分別爲,從站點到同倉庫的站點需要花費的時間。存在個特殊的站點,假如第個站點是特殊的,那麼可以花費的時間從一個區的號站點開到另一個區的號站點,只能通過這些特殊站點實現區與區之間的轉換。號,號兩個站點都是特殊的站點。
由於特殊的原因,在同一個區域內,只能在特殊站點掉頭,否則他們只能沿着同一個方向運行。現在正在區的站點上,他需要經過個給定的站點並回到原處,請問最少需要多少時間?你可以指定的初始方向。
做法
通過分類討論,我們可以知道最終情況只有以下四種。
每種情況分別通過二分計算即可。
這種情況只需要找到最接近最右側點而且在最右側點右側的關鍵點即可。
這種情況只需要找到能讓兩側轉變方向的最優關鍵點即可,對於這個的查詢可以直接用lower_bound查詢。
當所有點都在同一側,而且需要的關鍵點也在同一側時,可以直接這樣走。
代碼
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include<map>
#include<bitset>
#include<stack>
#include<set>
#include<vector>
#include <time.h>
#include<string.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair <ll, int> pli;
typedef pair <db, db> pdd;
const int maxn = 1e5+5;
const int Mod=1000000007;
const int INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const double e=exp(1);
const db PI = acos(-1);
const db ERR = 1e-10;
#define Se second
#define Fi first
#define pb push_back
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
vector<int>vec[2];//存放兩側要到達的點
vector<int>x;//存放關鍵點
int main()
{
int n,r,m,k,s,u,v;
scanf("%d%d%d%d%d",&n,&r,&m,&k,&s);
for(int i=1;i<=r;i++)
{
scanf("%d%d",&u,&v);
vec[v].push_back(u);
}
for(int i=1;i<=m;i++)
{
scanf("%d",&u);
x.pb(u);
}
x.pb(1);
x.pb(n);
int flag1=0,flag2=0;
sort(x.begin(),x.end());
int minn=n,maxx=1;
for(int i=0;i<vec[0].size();i++)
{
if(vec[0][i]>s) flag1=1;
if(vec[0][i]<s) flag2=1;
maxx=max(maxx,*(lower_bound(x.begin(),x.end(),vec[0][i])));//找到第一個在該點右側的關鍵點
minn=min(minn,*(upper_bound(x.begin(),x.end(),vec[0][i])-1));//找到第一個在該點左側的關鍵點
}
if(vec[1].size()==0)//所有點都在一側
{
if(flag1==0&&flag2==0) printf("0\n");//只有起點一個點
else if(flag1==0) printf("%d\n",2*(s-minn));//只有起點左側有點
else if(flag2==0) printf("%d\n",2*(maxx-s));//只有起點右側有點
else printf("%d\n",2*(maxx-minn));//起點兩側都有點
}
else
{
int minnb=n,maxxb=1;
for(int i=0;i<vec[1].size();i++)
{
maxxb=max(maxxb,*(lower_bound(x.begin(),x.end(),vec[1][i])));//找到第一個在該點右側的關鍵點
minnb=min(minnb,*(upper_bound(x.begin(),x.end(),vec[1][i])-1));//找到第一個在該點左側的關鍵點
}
maxx=max(maxx,maxxb);
minn=min(minn,minnb);
if(flag1==0&&maxxb<=s) printf("%d\n",(s-minn+k)*2);//只有起點左側有點
else if(flag2==0&&minnb>=s) printf("%d\n",(maxx-s+k)*2);//只有起點右側有點
else printf("%d\n",2*(maxx-minn+k));//起點兩側都有點
}
return 0;
}
B.吃豆豆
題意
有一個行列的棋盤,對於第行第列的格子,每過秒會在上面出現一個糖果,第一次糖果出現在第秒,糖果僅會在出現的那一秒存在,下一秒就會消失。假如第秒在第行第列的格子上,滿足,則會得到一個糖果。
假如當前在第行第列的格子上,那麼下一秒他可以選擇往上下左右走一格或停在原地。
現在請問從指定的出發到達指定的,並且在路上得到至少個糖果最少需要多少時間?
在的初始時間爲第秒。
做法
可以看到這道題都很小。
但是這道題的關鍵在於換一個方向思考問題,我們直接用表示到達點得到k個糖果的最短時間的話,是不能的,因爲上一個狀態不確定,無法。但是我們可以發現最後的答案一定不會超過,因爲我們可以站在一個位置不動,用這些時間就能達到目的,所以我們可用表示到達點經過時間能達到的最大糖果數,這就很容易了。只要從的能到達本點的狀態去轉移即可。最後找到能到在終點能得到個糖果的最短時間即可。
代碼
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int dp[15][15][12005];
int T[15][15];
int dis[5][2]={-1,0,1,0,0,-1,0,1,0,0};
int main()
{
int n,m,c;
memset(dp,-1,sizeof(dp));
scanf("%d%d%d",&n,&m,&c);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&T[i][j]);
}
}
int ans;
int stx,sty,enx,eny;
scanf("%d%d%d%d",&stx,&sty,&enx,&eny);
dp[stx][sty][0]=0;
for(int i=1;i<=10999;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=1;k<=m;k++)
{
for(int l=0;l<5;l++)
{
if(i%T[j][k]==0&&dp[j+dis[l][0]][k+dis[l][1]][i-1]!=-1)
{
dp[j][k][i]=max(dp[j][k][i],dp[j+dis[l][0]][k+dis[l][1]][i-1]+1);
}
else if(dp[j+dis[l][0]][k+dis[l][1]][i-1]!=-1)
{
dp[j][k][i]=max(dp[j][k][i],dp[j+dis[l][0]][k+dis[l][1]][i-1]);
}
}
}
}
if(dp[enx][eny][i]>=c)
{
ans=i;
break;
}
}
printf("%d\n",ans);
return 0;
}
C.拆拆拆數
題意
讀入,想請你把A拆成, 把B拆成, 滿足
1.對於所有的
2.
如果有多組滿足條件的和,請輸出最小的任意一組即可。
如果無解,請輸出。
做法
首先如果兩個數本來就是互質的,只分成一組即可
其餘的情況我們猜測分爲兩組即可
首先我們找到第一個不是的因子也不是的因子的質數
然後這樣拆分
因爲不是的倍數,所以不是的倍數,所以
因爲不是的倍數,所以不是的倍數,所以
因爲前15個質數相乘就已經大於 ,所以枚舉到第15個質數即可。
代碼
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include<map>
#include<bitset>
#include<stack>
#include<set>
#include<vector>
#include <time.h>
#include<string.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair <ll, int> pli;
typedef pair <db, db> pdd;
const int maxn = 1e5+5;
const int Mod=1000000007;
const int INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const double e=exp(1);
const db PI = acos(-1);
const db ERR = 1e-10;
#define Se second
#define Fi first
#define pb push_back
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
ll gcd_(ll a, ll b)
{
return b ==0? a : gcd_(b, a % b);
}
int prime[maxn];
int flag[maxn+5];//素數flag->0
int mp[maxn];
int tot;
void make_prime()
{
for(int i=2;i<=300;i++)
if(!flag[i])
{
prime[++tot]=i;
mp[i]=tot;
for(int j=i+i;j<=maxn;j+=i)
flag[j]=1;
}
}
int main()
{
make_prime();
int t;
scanf("%d",&t);
while(t--)
{
ll a,b;
scanf("%lld%lld",&a,&b);
if(gcd_(a,b)==1)
{
printf("1\n%lld %lld\n",a,b);
}
else if(a%2==1&&b%2==1)
{
printf("2\n");
printf("%lld %lld\n",2,b-2);
printf("%lld %lld\n",a-2,2);
}
else
{
ll n=a;
ll m=b;
ll tt;
for(int i=1;i<=15;i++)
{
if((a%prime[i]!=0)&&(b%prime[i]!=0))
{
tt=prime[i];
break;
}
}
if(tt>=n&&tt>=m)
{
printf("-1\n");
}
else
{
if(tt>=n)
{
ll x1,x2;
x2=m-tt;
ll tmpx=x2;
ll tmptt;
for(int i=1;i<=15;i++)
{
if(tmpx%prime[i]!=0)
{
tmptt=prime[i];
break;
}
}
x1=tmptt;
if(n-x1<=1) printf("-1\n");
else
{
printf("2\n");
printf("%lld %lld\n",x1,x2);
printf("%lld %lld\n",n-x1,m-x2);
}
}
else if(tt>=m)
{
swap(n,m);
ll x1,x2;
x2=m-tt;
ll tmpx=x2;
ll tmptt;
for(int i=1;i<=15;i++)
{
if(tmpx%prime[i]!=0)
{
tmptt=prime[i];
break;
}
}
x1=tmptt;
if(n-x1<=1) printf("-1\n");
else
{
printf("2\n");
printf("%lld %lld\n",x2,x1);
printf("%lld %lld\n",m-x2,n-x1);
}
}
else
{
printf("2\n");
printf("%lld %lld\n",tt,m-tt);
printf("%lld %lld\n",n-tt,tt);
}
}
}
}
return 0;
}
題意
做法
代碼
題意
做法
代碼
題意
做法
代碼
題意
做法
代碼