2019CSP-S模擬賽
阿新 • • 發佈:2020-07-24
2019CSP-S模擬賽
於2020/4,2020/7/24兩測
作為疫情期間學習過的證據
T1
#include<cmath> #include<cstdio> #include<cstdlib> #include<algorithm> #include<iostream> #include<string> #include<cstring> #include<queue> using namespace std; long long T; int xx[5010], yy[5010], xt, yt; long long ansx, ansy; string s; int main(){ freopen("robot.in","r",stdin); freopen("robot.out","w",stdout); cin >> s; // cout << s << endl; // scanf("%s",s+1); for(int i = 1; i <= s.size(); i++){ if(s[i-1] == 'E'){ xx[i] = xx[i - 1] + 1; yy[i] = yy[i - 1]; } else if(s[i-1] == 'W'){ xx[i] = xx[i - 1] - 1; yy[i] = yy[i - 1]; } else if(s[i-1] == 'N'){ yy[i] = yy[i - 1] + 1; xx[i] = xx[i - 1]; } else if(s[i-1] == 'S'){ yy[i] = yy[i - 1] - 1; xx[i] = xx[i - 1]; } // cout << xx[i] << " " << yy[i] << endl; } cin >> T; xt = xx[s.size()]; yt = yy[s.size()]; ansx += T / s.size() * xt; ansy += T / s.size() * yt; ansx += xx[T % s.size()]; ansy += yy[T % s.size()]; printf("%lld %lld\n", ansx, ansy); return 0; }
T2
矩陣快速冪
#include<cmath> #include<cstdio> #include<cstdlib> #include<algorithm> #include<iostream> #include<string> #include<cstring> #include<queue> #define ll long long #define MOD 1000000007 using namespace std; int t; ll n; struct mat{ ll m[4][4]; mat(){ memset(m, 0, sizeof(m)); } void base(){ m[1][3] = 1; m[2][1] = 1; m[3][2] = 1; m[3][3] = 1; } void pre(){ m[1][1] = 1; m[2][2] = 1; m[3][3] = 1; } }; mat operator *(mat a, mat b){ mat res; for(int i = 1; i <= 3; i++){ for(int j = 1; j <= 3; j++){ for(int k = 1; k <= 3; k++){ res.m[i][j] += a.m[i][k] * b.m[k][j]; res.m[i][j] %= MOD; } } } return res; } /* void print(mat a){ for(int i = 1; i <= 3; i++){ for(int j = 1; j <= 3; j++) cout << a.m[i][j] << " "; cout << endl; } } */ mat ksm(ll num){ mat ans, a; ans.pre(); a.base(); while(num){ if(num & 1){ ans = ans * a; } num >>= 1; a = a * a; /* print(ans); printf("\n"); print(a); printf("\n"); */ } return ans; } int main(){ freopen("seq.in","r",stdin); freopen("seq.out","w",stdout); scanf("%d",&t); while(t--){ scanf("%lld",&n); if(n <= 3){ printf("1\n"); } else{ mat ans = ksm(n - 3); // print(ans); ll Ans = 0; Ans += ans.m[1][3]; Ans %= MOD; Ans += ans.m[2][3]; Ans %= MOD; Ans += ans.m[3][3]; Ans %= MOD; printf("%lld\n", Ans); } } return 0; }
T3
對n個點分別建黑白兩點。
停留1秒轉化為從一種顏色的點走到本點的另一顏色的點。
跑最短路即可。
注意迷惑的題目描述。
u->v是從一秒前的u到一秒後的v,但是影響k值的顏色狀態全部取一秒之前。
停留,停留一秒後的顏色決定是否加s[i]。
做題歷程:
3個月前第一次做:這什麼玩意
3個月前聽WZ講:WOW,強!妙!
3個月前聽完後自己寫:
根據題意建圖,跑一遍spfa完事 搞成2n個點,前n個白,後n個黑 對於u,v,k 顏色一樣,add(u,v,k);add(u+n,v+n,k); 顏色不一樣, add(u,v+n,k-);add(u+n,v,k+) 處理完後,自己的黑白兩點相連 add(i,i+n,s[i]);add(i+n,i,0); spfa(1) spfa(1+n) ans=min(dist[n],dist[n*2]) 我的程式怎麼了嗚嗚嗚調不出來
OH,好,我發現當年真是沒有完全懂,程式寫的也不對。
3個月後,80pts。
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
#define ll long long
using namespace std;
const int maxn = 5010, maxm = 30010;
struct Edge{
int to, nxt;
ll k;
}ed[maxm * 2 + maxn * 2];
int n, m, first[maxn * 2], en, u, v;
ll k, w[maxn], s[maxn];
bool col[maxn * 2];
inline int read(){
int res = 0;
char c = getchar();
while(c < '0' || c > '9'){
c = getchar();
}
while(c <= '9' && c >= '0'){
res *= 10;
res += c - '0';
c = getchar();
}
return res;
}
inline ll llread(){
ll res = 0;
char c = getchar();
while(c < '0' || c > '9'){
c = getchar();
}
while(c <= '9' && c >= '0'){
res *= 10;
res += c - '0';
c = getchar();
}
return res;
}
void add(int u, int v, ll k){
ed[++en].to = v;
ed[en].k = k;
ed[en].nxt = first[u];
first[u] = en;
}
ll dist[maxn * 2];
bool inque[maxn * 2];
priority_queue <pair <int, int> > q;
void dijkstra(int s){
memset(dist, 0x3f, sizeof(dist));
dist[s] = 0;
inque[s] = 1;
q.push(make_pair(0,s));
while(q.size()){
int u = q.top().second;
q.pop();
for(int e = first[u]; e; e = ed[e].nxt){
int v = ed[e].to;
if(dist[v] > dist[u] + ed[e].k){
dist[v] = dist[u] + ed[e].k;
if(!inque[v]){
q.push(make_pair(-dist[v], v));
}
}
}
}
}
//完成後2mins,只看
int main(){
freopen("holes.in","r",stdin);
freopen("holes.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++){
col[i] = read();
col[i + n] = !col[i];
}
// for(int i = 1; i <= n + n; i++) cout << col[i] << " ";
// cout << endl;
for(int i = 1; i <= n; i++){
w[i] = llread();
}
for(int i = 1; i <= n; i++){
s[i] = llread();
if(col[i] == 0)//白洞
{
add(i, i + n, s[i]);
add(i + n, i, 0);
}
else {
add(i, i + n, 0);
add(i + n, i, s[i]);
}
}
for(int i = 1; i <= m; i++){
u = read(); v = read();
k = llread();
// scanf("%lld",&k);
if(col[u] == 0 && col[v] == 0)//w->b w-w
{
add(u, v + n, k);
add(u + n, v, k);
// add(u, v + n, (k - abs(w[u] - w[v]) )>= 0 ? (k - abs(w[u] - w[v]) ): 0);
// add(u + n, v, k + abs(w[u] - w[v]));
}
else if(col[u] == 0 && col[v] == 1)//w->w w-b
{
add(u, v + n, (k - abs(w[u] - w[v]) )>= 0 ? (k - abs(w[u] - w[v]) ): 0);
add(u + n, v, k + abs(w[u] - w[v]));
// add(u, v + n, k);
// add(u + n, v, k);
}
else if(col[u] == 1 && col[v] == 0)//b->b b-w
{
add(u, v + n, k + abs(w[u] - w[v]));
add(u + n, v, (k - abs(w[u] - w[v]) )>= 0 ? (k - abs(w[u] - w[v]) ): 0);
// add(u, v + n, k);
// add(u + n, v, k);
}
else if(col[u] == 1 && col[v] == 1)//b->w b-b
{
add(u, v + n, k);
add(u + n, v, k);
// add(u, v + n, k + abs(w[u] - w[v]));
// add(u + n, v, (k - abs(w[u] - w[v]) )>= 0 ? (k - abs(w[u] - w[v]) ): 0);
}
}
dijkstra(1);
ll ans;
if(dist[n] < dist[n + n]) ans = dist[n];
else ans = dist[n + n];
printf("%lld\n",ans);
return 0;
}
"%lld"!!!!!!!