[考试总结]noip模拟28
终于改掉了一看题目就想暴力的毛病
这次题目背景真的很有感觉。。
所以我无情地将其扒下来了。。。
“ 这个是为了发动奇迹所必要的准备阶段,是比较特殊的符卡。
明明就是准备的仪式却做成弹幕,真是聪明啊。
” ——《魔理沙的魔法书》
“ 虽然不清楚是不是那两人的力量
在那个风暴肆虐的夜晚,的确有一瞬
真的在那一瞬间,在云破天开的时候
透过空隙中看到的璀璨星空,不知为何倒映眼中不能忘怀 ” ——《奇迹召唤星辰》
“ 注视着属于我 独一无二的命运
席卷劲风 摧破结界
不再束缚于常识之海的我
撕裂大海 去开辟真正的道路吧
” ——《无尽的风之轨迹》
不水了。
\(T1\) 其实有个很显然的贪心,然后这个题也就没什么了,然后复杂度虽然我感觉不太对,然而考场上下发的打样例秒出了。。
所以感觉很稳。。
然而 \(T2\) 给我来了当头一棒。。。
暴力都 \(TM\) 打不对,然后经过我 \(2h\) 的努力,终于调出来了暴力。
然后只有一点点时间的时候开的 \(T3\),然后发现题目很难懂,其实是因为太中二了。。
但是最后还是过了大样例。。。
遗忘之祭仪
这个题目就是记录下来附节上的所有x
的位置。
然后对给出的大图进行遍历,之见到一个x
就要去填满,如果发现不合法,直接puts("No");
就行了。
%: pragma GCC optimize("O9")
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define debug cout<<"debug"<<endl
FILE *xinnb; int ak;
void openfile() {xinnb = freopen("t.txt","r",stdin);}
static const int maxn = 1e3+10,inf = 1e9+7;
namespace xin
{
char s[maxn];
int T,n,m,hang,lie;
int a[maxn][maxn];
class xin_data
{
public:
int x,y;
xin_data(){}
xin_data(int x,int y):x(x),y(y){}
}d[maxn*maxn];int zhi = 0;
inline void outa()
{
try(i,1,n)
{
try(j,1,m) cout<<a[i][j]<<' ';
cout<<endl;
}
cout<<endl;
}
inline bool check(int x,int y)
{
try(i,1,zhi)
{
register int dx = x + d[i].x - 1,dy = y + d[i].y - 1;
// cout<<"dx = "<<dx<<" dy = "<<dy<<endl;
// outa();
if(dx > n or dy > m or !a[dx][dy]) {return false;}
a[dx][dy] = 0;
}
return true;
}
inline short main()
{
#ifndef ONLINE_JUDGE
openfile();
#endif
ak = scanf("%d",&T);
while(T--)
{
zhi = 0;
ak = scanf("%d%d%d%d",&n,&m,&hang,&lie);
try(i,1,n)
{
ak = scanf("%s",s+1);
try(j,1,m) a[i][j] = (s[j] == 'x');
}
bool fir = 0;
try(i,1,hang)
{
ak = scanf("%s",s+1);
try(j,1,lie)
{
register int x,y;
if(s[j] == 'x')
{
if(!fir) x = i,y = j,fir = 1;
d[++zhi] = xin_data(i-x+1,j-y+1);
}
}
}
if(zhi == 0) {printf("No\n"); continue;}
bool ok = 1;
try(i,1,n) if(ok) try(j,1,m)
{
if(a[i][j])
{
if(!check(i,j)) {puts("No"); ok = 0; break;}
}
}
if(ok) puts("Yes");
}
return 0;
}
}
signed main(){return xin::main();}
客星璀璨之夜
直观的暴力就是先枚举排列,然后再去枚举每一个方向,之后再 \(check\)
我因为自己能够搞掉 \(n=10\) 的点,然而跑了 \(10min\)
正解首先我们推出来概率,之后再乘上每一段的 \(x_i - x_{i-1}\)。
但是细节挺多的。。
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define int long long
namespace xin_io
{
#define scanf nb = scanf
#define debug cout<<"debug"<<endl
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<2,stdin),p1 == p2) ? EOF : *p1++
char buf[1<<20],*p1 = buf,*p2 = buf,output[100]; FILE *xinnb;int nb;typedef long long ll; typedef unsigned long long ull;
void openfile() {xinnb = freopen("t.txt","r",stdin);} void outfile() {xinnb = freopen("o.txt","w",stdout);}
inline int get()
{
register int s = 0,f = 1; register char ch = gc(); while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc();return s * f;
}
template<typename type>inline void write(type x,char out)
{
if(!x) return putchar('0'),putchar(out),void(); if(x < 0) putchar('-'),x = -x;
register int cnt = 0;while(x) output[++cnt] = x % 10,x /= 10;
throw(i,cnt,1) putchar(output[i] xor 48);return putchar(out),void();
}
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7,mod = 998244353; static const ll llinf = 1e17+7;
namespace xin
{
inline int ksm(int x,int y)
{
register int ret = 1;
while(y)
{
if(y & 1) ret = ret * x % mod;
x = x * x % mod; y >>= 1;
}
return ret % mod;
}
int f[maxn*3/1000][maxn*6/1000],n,x[maxn];
int jsq1,jsq2;
inline short main()
{
#ifndef ONLINE_JUDGE
openfile();
#endif
n = get();
try(i,1,((n<<1)|1)) x[i] = get();
try(i,1,n)
{
register int er = ksm((i<<1),mod-2),yi = ksm(i,mod-2);
try(j,2,(i<<1|1))
{
int temp = (((i << 1) | 1) - j) >> 1;
if(j & 1) (f[i][j] += f[i-1][j] * temp % mod * yi % mod + f[i-1][j-1] * er % mod + f[i-1][j-2] * er % mod + er + (i - temp - 1) * f[i-1][j-2] % mod * yi % mod) %= mod;
else (f[i][j] += f[i-1][j] * temp % mod * yi % mod + f[i-1][j] *er % mod + er % mod + f[i-1][j-1] * er % mod + (i - temp - 1) * f[i-1][j-2] % mod * yi) %= mod;
// cout<<"i = "<<i<<" j = "<<j<<" f[i][j] = "<<f[i][j]<<endl;
}
}
int ans = 0;
try(i,2,(n<<1 | 1)) (ans += f[n][i] * ( x[i] - x[i-1])) %= mod;
cout<<ans<<endl;
return 0;
}
}
signed main(){return xin::main();}
割海成路之日
这个暂时只有 \(25pts\) 垃圾做法。
还没想出来正解。。。
菜爆了。。。
只有 \(25pts\;code\)
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
namespace xin_io
{
#define scanf nb = scanf
#define debug cout<<"debug"<<endl
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<2,stdin),p1 == p2) ? EOF : *p1++
char buf[1<<20],*p1 = buf,*p2 = buf,output[100]; FILE *xinnb;int nb;typedef long long ll; typedef unsigned long long ull;
void openfile() {xinnb = freopen("t.txt","r",stdin);} void outfile() {xinnb = freopen("o.txt","w",stdout);}
inline int get()
{
register int s = 0,f = 1; register char ch = gc(); while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc();return s * f;
}
template<typename type>inline void write(type x,char out)
{
if(!x) return putchar('0'),putchar(out),void(); if(x < 0) putchar('-'),x = -x;
register int cnt = 0;while(x) output[++cnt] = x % 10,x /= 10;
throw(i,cnt,1) putchar(output[i] xor 48);return putchar(out),void();
}
}
using namespace xin_io; static const int maxn = 3e6+10,inf = 1e9+7; static const ll llinf = 1e17+7;
namespace xin
{
class xin_edge{public:int next,ver,w;}edge[maxn];
int head[maxn],cnt = 1;
inline void add(int x,int y,int w) {edge[++cnt].ver = y; edge[cnt].w = w ; edge[cnt].next = head[x]; head[x] = cnt;}
int n,m;
int dep[maxn],f[maxn][24],fr[maxn],lg[maxn],num = 0;
std::unordered_map<int,int>e[maxn];
void pre_dfs(int x,int fa)
{
dep[x] = dep[fa] + 1;
f[++num][0] = x;
if(!fr[x]) fr[x] = num;
for(register int i=head[x];i;i=edge[i].next)
{
register int y = edge[i].ver;
if(y == fa) continue;
pre_dfs(y,x);
f[++num][0] = x;
if(!fr[x]) fr[x] = num;
}
}
void RMQ()
{
for(register int j=1;(1<<j)<=num;++j)
for(register int i=1;i+(1<<j)-1<=num;++i)
if(dep[f[i][j-1]]<dep[f[i+(1<<(j-1))][j-1]])f[i][j]=f[i][j-1];
else f[i][j]=f[i+(1<<(j-1))][j-1];
try(i,2,num) lg[i] = lg[i>>1] + 1;
}
int lca(int x,int y)
{
x = fr[x]; y = fr[y];
if(x > y) x ^= y ^= x ^= y;
int len=lg[y-x+1];
return dep[f[x][len]]<dep[f[y-(1<<len)+1][len]]?f[x][len]:f[y-(1<<len)+1][len];
}
bool ok = 0,shit = 1;
void dfs1(int x,int goal)
{
if(x == goal or !shit) return ;
for(register int i=head[x];i;i=edge[i].next)
{
register int y = edge[i].ver,z = edge[i].w;
if(dep[y] > dep[x]) continue;
if(ok and z > 1) {shit = 0; return ;}
if(z == 3) ok = 1;
dfs1(y,goal);
}
}
void dfs2(int x,int goal)
{
if(x == goal ) return ;
for(register int i=head[x];i;i=edge[i].next)
{
register int y = edge[i].ver,z = edge[i].w;
if(dep[y] > dep[x]) continue;
dfs2(y,goal);
if(ok and z > 1) {shit = 0; return ;}
if(z == 3) ok = 1;
}
}
inline bool check(int x,int y)
{
register int goal = lca(x,y); ok = 0; shit = 1;
dfs1(x,goal); dfs2(y,goal);
return shit;
}
inline short main()
{
#ifndef ONLINE_JUDGE
openfile();
#endif
n = get(); m = get();
try(i,1,n-1)
{
register int x = get(),y = get(),z = get();
add(x,y,z); e[x][y] = e[y][x] = cnt;
add(y,x,z);
}
pre_dfs(1,0); RMQ();
try(i,1,m)
{
register int x = get(),y = get(),s = get(),t = get(),ans = 0;
if(edge[e[x][y]].w xor 1) edge[e[x][y]].w--,edge[e[x][y] xor 1].w--;
write(check(t,s),' ');
try(i,1,n) if(check(i,s)) {/*cout<<"i = "<<i<<endl; */ans++;}
write(ans,'\n');
}
return 0;
}
}
signed main(){return xin::main();}