CSP11
T1
暴力
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define ull unsigned long long
#define lid (rt<<1)
#define rid (rt<<1|1)
// #define endl '\n'
//#define int long long
#define pb push_back
// #pragma comment(linker, ¡°/STACK:512000000,512000000¡±)
using namespace std;
const int N = 2e5+5,mod=1e9+7,inf=1e9;
int n,m,dis[N];bool vis[N];
vector <int> edge[N];
struct Node
{
int dis,u;
bool operator < (const Node& A)const
{
return dis>A.dis;
}
};
int st,en;
void dij(int st)
{
for(int i=1;i<=n;i++)dis[i]=1e9;
priority_queue <Node> q;
q.push({0,st});
dis[st]=0;
while(q.size())
{
int u=q.top().u;q.pop();
if(vis[u])continue;
vis[u]=1;
for(auto to:edge[u])
{
if(vis[to])continue;
if(dis[to]>dis[u]+1)
{
dis[to]=dis[u]+1;
q.push({dis[to],to});
}
}
}
}
inline ll dfs(const int u,const int step,const int tg)
{
if(step>tg||(step==tg&&u!=en))return 0;//這兩個特判最佳化不少
if(u==en)return step==tg;
vis[u]=1;
ll res=0;
for(auto to:edge[u])
{
if(vis[to])continue;
res=(dfs(to,step+1,tg)+res)%mod;
}
vis[u]=0;
return res;
}
int main()
{
speed();
// freopen("Fate1.in","r",stdin);
// freopen("Fate9.in","r",stdin);
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
cin>>n>>m;
cin>>st>>en;
// cout<<"**********"<<endl;
int u,v;
for(int i=1;i<=m;i++)
{
cin>>u>>v;
edge[u].pb(v);edge[v].pb(u);
}
dij(st);
memset(vis,0,sizeof vis);
int tg=dis[en]+1;
cout<<dfs(st,0,tg);
return 0;
}
我們其實沒必要\(dfs\)找一遍,其實可以直接\(BFS\),從起點開始,\(f\)表示最短路徑的數量,\(g\)表示最短路徑+1的數量
如何轉移?,設當前為\(u->to\),\(dis_u==dis_{to}則g_{u}+=f_{to}\)\(dis_{to}=dis_u+1,則g_{to}+=g_u,f_{to}+=f_u\)
注意順序一定不能換,否則\(g_u\)不上
點選檢視程式碼
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define ull unsigned long long
#define lid (rt<<1)
#define rid (rt<<1|1)
// #define endl '\n'
//#define int long long
#define pb push_back
#define pii pair<int,int>
// #pragma comment(linker, ¡°/STACK:512000000,512000000¡±)
using namespace std;
const int N = 2e5+5,mod=1e9+7,inf=1e9;
int n,m,dis[N],g[N],f[N],id[N];bool vis[N];
vector <int> edge[N];
vector <pii> G;
struct Node
{
int dis,u;
bool operator < (const Node& A)const
{
return dis>A.dis;
}
};
int st,en;
void dij(int st)
{
for(int i=1;i<=n;i++)dis[i]=1e9;
priority_queue <Node> q;
q.push({0,st});
dis[st]=0;
while(q.size())
{
int u=q.top().u;q.pop();
if(vis[u])continue;
vis[u]=1;
for(auto to:edge[u])
{
if(vis[to])continue;
if(dis[to]>dis[u]+1)
{
dis[to]=dis[u]+1;
q.push({dis[to],to});
}
}
}
}
// unordered_map <int,map<int,int>> dp;
// inline ll dfs(const int u,const int step,const int tg)
// {
// if(step>tg||(step==tg&&u!=en))return 0;
// if(u==en)return step==tg;
// if(dp[u][step])return dp[u][step];
// // cout<<step<<endl;
// vis[u]=1;
// ll res=0;
// for(auto to:edge[u])
// {
// if(vis[to])continue;
// res=(dfs(to,step+1,tg)+res)%mod;
// }
// vis[u]=0;
// return dp[u][step]=res;
// }
int main()
{
speed();
// freopen("Fate1.in","r",stdin);
// freopen("Fate9.in","r",stdin);
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
cin>>n>>m;
cin>>st>>en;
// cout<<"**********"<<endl;
int u,v;G.pb({0,0});
for(int i=1;i<=m;i++)
{
cin>>u>>v;
G.pb({u,v});
edge[u].pb(v);edge[v].pb(u);
}
dij(st);
memset(vis,0,sizeof vis);
auto ans=[&](int st,int en)
{
queue <int> q;
q.push(st);
f[st]=1;
// vis[st]=1;
while(q.size())
{
int u=q.front();q.pop();
// if(vis[u])continue;
// vis[u]=1;
for(auto to:edge[u])
{
if(dis[u]==dis[to])
{
g[u]+=f[to];g[u]%=mod;
// q.push(to);
}
}
for(auto to:edge[u])
{
if(dis[to]==dis[u]+1)
{
g[to]+=g[u];
f[to]+=f[u];
g[to]%=mod;f[to]%=mod;
if(!vis[to])vis[to]=1,q.push(to);
}
}
}
return g[en];
};
ll p=ans(st,en);
cout<<p<<endl;
return 0;
}
T2
暴力
點選檢視程式碼
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4+5;
int sum[N];
int n,a;
struct Fs
{
int x,w,v;
double dis;
}f[N];
bool cmp(Fs a,Fs b)
{
return a.x<b.x;
}
bool cmpdis(Fs a,Fs b)
{
return a.dis<b.dis;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
// freopen("EVA1.in","r",stdin);
cin>>n>>a;
bool ev=1;
for(int i=1;i<=n;i++)
{
cin>>f[i].w>>f[i].x>>f[i].v;
if(i>1&&f[i].v!=f[1].v)ev=0;
}
if(ev)
{
// cout<<"****"<<endl;
sort(f+1,f+1+n,cmp);
for(int i=1;i<=n;i++)sum[f[i].x]+=f[i].w;
for(int i=1;i<=f[n].x;i++)sum[i]+=sum[i-1];
int ans=0;
for(int i=1;i<=f[n].x;i++)
{
ans=max(ans,sum[min(i+a,f[n].x)]-sum[i-1]);
}
cout<<ans<<endl;
return 0;
}
// for(int i=1;i<=n;i++)
// cout<<"****"<<endl;
int ans=0;
for(double t=0.0001;t<=1;t+=0.0001)
{
for(int i=1;i<=n;i++)
{
f[i].dis=f[i].x+f[i].v*t;
}
sort(f+1,f+1+n,cmpdis);
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+f[i].w;
int st=1;
for(int i=1;i<=n;i=-~i)
{
while(f[i].dis-a>f[st].dis)st++;
ans=max(ans,sum[i]-sum[st-1]);
}
}
for(double t=0.001;t<=10;t+=0.02)
{
for(int i=1;i<=n;i++)
{
f[i].dis=f[i].x+f[i].v*t;
}
sort(f+1,f+1+n,cmpdis);
for(int i=1;i<=n;i=-~i)sum[i]=sum[i-1]+f[i].w;
int st=1;
for(int i=1;i<=n;i=-~i)
{
while(f[i].dis-a>f[st].dis)st++;
ans=max(ans,sum[i]-sum[st-1]);
}
}
cout<<ans;
return 0;
}
/*
3 10
1 15 55
10 20 55
100 25 55
*/
正解是列舉每一條魚,設為\(i\)作為左端點(一定是最優的),透過相對速度,算出每一條魚對它的貢獻\(l_t,r_t\),進行差分即可
一些細節問題,
精度問題
還有判斷\(r\)是負數的情況不能要
速度相等的情況要注意
由於精度問題\(l,r\)可能要互換位置,先要換位置,再判斷是否\(r<0\)
關於差分時,右端點\(r\)要加上一個\(eps\),就是為了先讓魚進來,再讓魚出去,以滿足答案最優
點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e4+5;
const double eps=1e-9;
int sum[N];
int n,a,cnt[N],jcnt[N];
struct Fs
{
int x,w,v;
}f[N];
bool cmp(Fs a,Fs b)
{
return a.x<b.x;
}
map <double,int> tmm;
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
// freopen("EVA1.in","r",stdin);
cin>>n>>a;
for(int i=1;i<=n;i++)
{
cin>>f[i].w>>f[i].x>>f[i].v;
}
sort(f+1,f+1+n,cmp);ll ans=0;
for(int i=1;i<=n;i++)
{
tmm.clear();
ll res=f[i].w;
for(int j=1;j<=n;j++)
{
if(i==j)continue;
if(f[j].v==f[i].v)
{
if(f[j].x>=f[i].x&&f[j].x-f[i].x<=a)res+=f[j].w;
// cout<<res<<endl;
continue;
}
// if(f[j].x<f[i].x&&f[j].v<=f[i].v)continue;
double l=1.0*(f[i].x-f[j].x)/(f[j].v-f[i].v);
double r=1.0*(f[i].x-f[j].x+a)/(f[j].v-f[i].v);
// cout<<t<<" "<<r<<rdl;
// if(t<0)continue;
if(l>r-eps)swap(l,r);//先要換位置,再判斷是否r<0
if(r<0)continue;
l=max(l,0.0000);
tmm[l]+=f[j].w;
tmm[r+eps]-=f[j].w;
// if(f[j].x>f[i].x&&f[j].v>=f[i].v&&f[j].x-f[i].x>a)continue;
}
ans=max(ans,res);
for(auto it:tmm)
{
res+=(it.second);
ans=max(ans,res);
}
}
cout<<ans;
return 0;
}
/*
3 10
1 15 55
10 20 55
100 25 55
*/
T3
計數題
做法一:
排序\(a\)陣列,然後,我們初始左右指標\(l=1,r=n\),在滿足\(l<r企鵝a[l]+a[r]>=k\)的情況下不斷讓\(r\)指標右移,這樣,一定會有一個邊界,使得左端點\(a_l\)只能與\([r,n]\)的\(a\)匹配,我們把他們加入到數列中,用\(ans\)乘上貢獻,類似插空的思想,當前未放入\(a_l,a_r\),
數列中已經包含\([1,l-1],[r+1,n]\),這樣就有\(n-r+l-1+1\)個空,再減去有\([1,l-1]\)元素周圍不能放\(a_r,a_l\)所以,貢獻為\(n-r+l-2\times (l-1)\),但是要注意最後還用相同數的情況,所以乘上相同數階乘的逆元即可
點選檢視程式碼
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define ull unsigned long long
#define lid (rt<<1)
#define rid (rt<<1|1)
#define endl '\n'
//#define int long long
#define pb push_back
// #pragma comment(linker, ¡°/STACK:512000000,512000000¡±)
using namespace std;
const int N = 2e5+5,mod=998244353,inf=1e9;
ll n,k,a[N],jie[N];
ll qpow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}
return ans;
}
ll calc(ll l,ll r)
{
return (n-l-r+2);
}
int main()
{
speed();
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
jie[0]=1;
for(ll i=1;i<=n;i++)jie[i]=jie[i-1]*i%mod;
sort(a+1,a+1+n);
ll l=1,r=n;
ll ans=1;
while(l<=r)
{
while(l<r&&a[r]+a[l]>=k)
{
ans=ans*calc(l,r)%mod;
r--;
}
ans=ans*calc(l,r)%mod;
l++;
}
ll cnt=1;
a[n+1]=inf;
for(int i=2;i<=n+1;i++)
{
if(a[i]==a[i-1])cnt++;
else
{
ans=ans*qpow(jie[cnt],mod-2)%mod;
cnt=1;
}
}
cout<<ans<<endl;
// for()
return 0;
}