之前进行了一星期的胡策,一直坑着没写233,今天决定补上。
由于不可描述的原因,进行了为期一周的队内胡策(互相伤害),每次出题人不同,题目方向不同,但所有算法确实是在noip范围内,都是套路啊,被学弟学妹们虐的死去活来233。
round 1
round 1 由swc , imcy , xczhw三位老年选手出题╮(╯▽╰)╭。题目大都可以找到原题233.
T1
swc正在找题的时候,imcy突然发现这个题只要换下输入就非常劲233,于是就有了t1,有了这个样例
实际效果非常有视觉冲击力233.
所以说题解就是求个连通块。
std如下
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int map[500][500];
struct doubi{
int x,y;
};
int n,m;
queue<doubi> q;
int x_x[13]={0,0,0,1,-1,1,1,-1,-1,0,0,2,-2};
int y_y[13]={0,1,-1,0,0,1,-1,1,-1,2,-2,0,0};
bool can(int x,int y)
{
if(x>=1&&x<=n&&y>=1&&y<=m)
return true;
return false;
}
void bfs(int i,int j)
{
doubi s;
s.x=i,s.y=j;
q.push(s);
while(!q.empty())
{
doubi u=q.front();
q.pop();
int x=u.x,y=u.y;
for(int i=1;i<=12;i++){
int X=x+x_x[i];
int Y=y+y_y[i];
if(can(X,Y)&&map[X][Y]){
doubi nxt;
nxt.x=X,nxt.y=Y;
q.push(nxt);
map[X][Y]=0;
}
}
}
}
int main()
{
freopen("chinese.in","r",stdin);
freopen("chinese.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
string x;
cin>>x;
if(x=="井号"){
map[i][j]=1;
}
}
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(map[i][j]){
bfs(i,j);
ans++;
}
}
}
cout<<ans<<endl;
fclose(stdin);
fclose(stdout);
return 0;
}
T2
一个USACO的题目,当时做的时候一眼建图,然后打了个最短路233,发现样例过不了,仔细阅读题目后,神tm最短路,把每个点都连起来再加上几个井,明明是最小生成树233,题目沿用了luogu.org上的翻译.
std如下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int size = 200010;
int n;
int num[size];
struct dc
{
int f,t,d;
}l[size];
int tot = 1;
void build(int f,int t,int d)
{
l[tot].f = f;
l[tot].t = t;
l[tot].d = d;
tot ++;
}
int f[size];
int find(int x)
{
if(f[x] == x)
return x;
return f[x] = find(f[x]);
}
bool cmp(dc a,dc b)
{
return a.d < b.d;
}
void init()
{
tot = 1;
memset(num,0,sizeof(num));
memset(l,0,sizeof(l));
memset(f,0,sizeof(f));
}
int main()
{
freopen("farmer_m.in","r",stdin);
freopen("farmer_m.out","w",stdout);
scanf("%d",&n);
for(int i = 1 ; i <= n ; i ++)
scanf("%d",&num[i]) , f[i] = i;
for(int i = 1 ; i <= n ; i ++)
for(int j = 1 ; j <= n ; j ++)
{
int d;
scanf("%d",&d);
build(i,j,d);
}
for(int i = 1 ; i <= n ; i ++)
build(0,i,num[i]);
sort(l+1,l+tot,cmp);
int ans = 0;
for(int i = 1 ; i < tot ; i ++)
{
int ff = l[i].f , ft = l[i].t;
if(find(ff) != find(ft))
{
f[find(ff)] = find(ft);
ans += l[i].d;
}
}
printf("%d\n",ans);
fclose(stdin);
fclose(stdout);
return 0;
}
T3
题目是faebdc神犇曾给提供的模拟赛的t3,题面被魔改的非常辣眼233.一个树上LCA乱搞的好题,具体见代码
std如下
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define KILL puts("haha");
using namespace std;
typedef long long ll;
const ll MAXN = 100000 + 5;
const ll MAXM = 100000 + 5;
const ll P = 1e9 + 7;
struct edge
{
ll f,t,v;
}l[MAXM << 1];
ll first[MAXN],next[MAXM << 1],tot;
ll n;
void init()
{
memset(first,0xfff,sizeof(first));
tot = 0;
return;
}
void build(ll f,ll t,ll v)
{
l[++tot] = (edge){f,t,v};
next[tot] = first[f];
first[f] = tot;
return;
}
ll fa[MAXN][35],deep[MAXN];
void get_fa()
{
for(int j = 1;j <= 30;j ++)
for(int i = 1;i <= n;i ++)
fa[i][j] = fa[fa[i][j - 1]][j - 1];
}
ll lca(ll x,ll y)
{
if(deep[x] < deep[y])
swap(x,y);
for(int j = 30;j >= 0;j --)
if(deep[fa[x][j]] >= deep[y])
x = fa[x][j];
if(x == y)
return x;
for(int j = 30;j >= 0;j --)
if(fa[x][j] != fa[y][j])
x = fa[x][j],y = fa[y][j];
return fa[x][0];
}
ll sz[MAXN];
void dfs(ll x,ll f)
{
fa[x][0] = f;
sz[x] = 1;
deep[x] = deep[f] + 1;
for(int i = first[x];~i;i = next[i])
if(l[i].t != f)
{
dfs(l[i].t,x);
sz[x] += sz[l[i].t];
}
return;
}
ll root[MAXN];
ll ci(ll x,ll y)
{
if(deep[x] < deep[y])
swap(x,y);
return sz[x] * (n - sz[x]);
}
void dfs(ll x)
{
root[x] = root[fa[x][0]] + ci(fa[x][0],x);
for(int i = first[x];~i;i = next[i])
if(l[i].t != fa[x][0])
dfs(l[i].t);
return;
}
ll ans = 0;
void solve()
{
for(int i = 1;i <= tot;i += 2)
ans += (ci(l[i].f,l[i].t) % P * l[i].v % P) % P,ans %= P;
ans %= P;
return;
}
ll m;
ll f,t,v;
ll read()
{
ll x = 0 , f = 1;
char in = getchar();
while(in < '0' || in > '9')
{
if(in == '-')
f = -1;
in = getchar();
}
while(in >= '0' && in <= '9')
{
x = (x << 3) + (x << 1) + in - '0';
in = getchar();
}
return x * f;
}
int main()
{
freopen("MaHouShaoJiuDQS.in","r",stdin);
freopen("MaHouShaoJiuDQS.out","w",stdout);
init();
n = read();
for(int i = 1;i < n;i ++)
{
f = read() , t = read() , v = read();
while(v < 0)
v += P;
v %= P;
build(f,t,v);
build(t,f,v);
}
dfs(1,0);
get_fa();
dfs(1);
solve();
printf("%lld\n",ans);
m = read();
for(int i = 1;i <= m;i ++)
{
f = read() , t = read() , v = read();
while(v < 0)
v += P;
v %= P;
ans = ((ans % P + (root[f] % P + root[t] % P - ((root[lca(f,t)] % P) << 1) % P) % P * (v % P)) % P) % P;
while(ans < 0)
ans += P;
printf("%lld\n",ans % P);
ans %= P;
}
fclose(stdin);
fclose(stdout);
return 0;
}
这次胡策学弟(妹)们表现的还不错,该A的A,该暴力的暴力233.
round 2
round 2 由 black,francis,knight,qer出题。
T1
看完题一脸蒙蔽233,开始手推公式,半小时后放弃,一个半小时后打出表来发现正解233,知道正解后才想起来之前好像听哪位学长说过fib的公比为(√5 - 1)/2,于是A掉T1,差点被套路到233。
代码如下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
unsigned long long f[450];
int main()
{
freopen("DQSjangke.in","r",stdin);
freopen("DQSjangke.out","w",stdout);
unsigned long long n;
int m;
cin>>n;
f[0] = 1;
f[1] = 1;
for(int i = 2 ; ; i ++)
{
f[i] = f[i-1] + f[i-2];
if(f[i] > n || f[i] < 0)
{
m = i;
break;
}
}
m --;
cout<<f[m-1]<<"/"<<f[m];
fclose(stdin);
fclose(stdout);
return 0;
}
T2
看完题还是一脸蒙蔽,T1已经用了一半时间,这个题也没多想,感觉贪心好像可以,每次拿一个尽量大且合法的分离器装上,然后简单想了下证明,复杂度O(k),就直接T3了,考完才发现k是10^9,只拿了部分分+手动读入骗来的分,加个二分就可以过了,还可以O(1)求解,然而我不会233。
std如下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
void read(ll &n)
{
n = 0;
char a = getchar();
while(a<'0'||a>'9')
a = getchar();
while(a>='0'&& a<='9')
{
n*=10;
n+=a-'0';
a = getchar();
}
}
int main()
{
freopen("project.in", "r", stdin);
freopen("project.out", "w", stdout);
ll n, k, d, t;
read(n);read(k);
d=k*k - k - 2*n + 2;
if(d < 0)
puts("-1");
else
{
t = (int)(sqrt(d));
printf("%lld", k-1-t+(t*t+t>d));
}
}
加了一点点特技的背包,然而当时没时间了比较慌,没想到n^2算法,于是大力暴力n^3,神tmA了233.
代码如下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
ll read()
{
int x = 0 , f = 1;
char in = getchar();
while(in < '0' || in > '9')
{
if(in == '-')
f = -1;
in = getchar();
}
while(in >= '0' && in <= '9')
{
x = x * 10 + in - '0';
in = getchar();
}
return x * f;
}
ll f[4010];
int m,n;
ll w[2010],a[2010],b[2010];
int main()
{
freopen("candy.in","r",stdin);
freopen("candy.out","w",stdout);
scanf("%d%d",&m,&n);
for(int i = 1 ; i <= n ; i ++)
w[i] = read() , a[i] = read() , b[i] = read();
for(int i = 1 ; i <= n ; i ++)
for(int j = m ; j >= w[i] ; j --)
for(int k = 1 ; j - k * w[i] >= 0 ; k ++)
f[j] = max(f[j],f[j-k*w[i]]+k*(a[i]+b[i])-(k-1)*b[i]);
printf("%lld\n",f[m]);
fclose(stdin);
fclose(stdout);
return 0;
}
/*
100 2
10 2 1
20 1 50
68
*/
T4
题解强行noip233,就是把数位dp的过程搞了下,数位dp不可免233,非noip内容这里就不bb了。
std如下
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
typedef long long LL;
const int MAXN = 65;
LL c[MAXN][MAXN];
LL bin[MAXN];
void read(LL &n)
{
n = 0;
char a = getchar();
while(a<'0'||a>'9')
a = getchar();
while(a>='0'&& a<='9')
{
n*=10;
n+=a-'0';
a = getchar();
}
}
void init()
{
for(int i = 0; i < MAXN; i ++)
c[i][0] = 1;
for(int i = 1; i < MAXN; i ++)
for(int j = 1; j < MAXN; j ++)
c[i][j] = c[i-1][j] + c[i-1][j-1];
}
LL Get_bin(LL x)
{
bin[0] = 0;
while(x)
{
bin[++bin[0]] = x%2;
x >>= 1;
}
}
LL Get_Rn(LL x)
{
LL sum = 0;
Get_bin(x); // 获得二进制数
// 长度小于 x
for(int i = bin[0]-1; i > 1; i --)
for(int j = (i+1)/2; j <= i-1; j ++)
sum += c[i-1][j];
// sum = 0;
// 长度等于 x // 需要的 0 恒大于 (bin[0]+1)/2
LL zero = 0;
for(LL i = bin[0]-1; i >= 1; i --) // 本来就有一个 1
if(bin[i])
for(LL j = ((bin[0]+1)/2)-1-zero; j <= i-1; j ++)
sum += c[i-1][j];
else zero ++;
return sum;
}
int main()
{
freopen("Oierdqs.in","r",stdin);
freopen("Oierdqs.out","w",stdout);
LL a, b;
read(a);read(b);
init();
// cout << Get_Rn(b+1) << endl;
printf("%llu", Get_Rn(b+1)-Get_Rn(a));
return 0;
}
round 2的t1,t2都挺有意思的,不失为一种思路,数位dp我刚接触没几天,对t4不做评价,t3有点裸了,恩恩,不过学弟们的题贼带劲。
round 3
round 3 是 jhz lcy ljx msy zzk出题,题目贼劲啊,神tmT2就到ctsc了233.
T1
一个有坑的暴力题,注意下边界没啥问题。
代码如下
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
ll num[511][511];
int n;
int px,py;
bool check()
{
ll ans = 0 , temp = 0;
for(int i = 1 ; i <= n ; i ++)
ans += num[i][i];
for(int i = 1 ; i <= n ; i ++)
temp += num[i][n-i+1];
if(ans != temp)
return false;
for(int i = 1 ; i <= n ; i ++)
{
temp = 0;
for(int j = 1 ; j <= n ; j ++)
temp += num[i][j];
if(temp != ans)
return false;
}
for(int i = 1 ; i <= n ; i ++)
{
temp = 0;
for(int j = 1 ; j <= n ; j ++)
temp += num[j][i];
if(temp != ans)
return false;
}
return true;
}
int main()
{
freopen("business.in","r",stdin);
freopen("business.out","w",stdout);
scanf("%d",&n);
for(int i = 1 ; i <= n ; i ++)
for(int j = 1 ; j <= n ; j ++)
{
scanf("%lld",&num[i][j]);
if(num[i][j] == 0)
px = i , py = j;
}
int pos = 0;
if(n == 1)
{
puts("1");
fclose(stdin);
fclose(stdout);
return 0;
}
else if(px == 1)
pos = 2;
else if(px == n)
pos = n - 1;
else
pos = px + 1;
ll ans = 0;
for(int i = 1 ; i <= n ; i ++)
ans += num[pos][i];
for(int i = 1 ; i <= n ; i ++)
ans -= num[px][i];
num[px][py] = ans;
if(check())
printf("%lld\n",ans);
else
puts("-1");
fclose(stdin);
fclose(stdout);
return 0;
}
T2
对字符串的题一直不敏感233,做到这一脸懵逼,思考过后决定打暴力233.
考完后知道原题是ctsc的,吓尿了233,正解是hash。
std如下
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
typedef unsigned long long ULL;
const int p = 2333;
char s[30010][550];
ULL hash[50000], py[500], ls[50000];
int main()
{
freopen("gbwl.in", "r", stdin);
freopen("gbwl.out", "w", stdout);
int len, n, si;
scanf("%d%d%d", &n, &len, &si);
py[0] = 1;
for(int i = 1; i <= 210; i++)
py[i] = py[i - 1] * p;
for(int i = 1; i <= n; i++)
scanf("%s", s[i] + 1);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= len; j++)
hash[i] = hash[i] * p + s[i][j];
int pr = 1, ans = 0;
for(int i = 1; i <= len; i++)
{
for(int j = 1; j <= n; j++)
ls[j] = hash[j] - s[j][i] * py[len - i];
sort(ls + 1, ls + n + 1);
for(int j = 2; j <= n; j++)
{
if(ls[j] == ls[j - 1])
{
ans += pr;
pr ++;
}
else
pr = 1;
}
}
printf("%d", ans);
return 0;
T3
去年noiptg组day2t3原题,然而我现在还是不会233,直接上分段函数,palapala打了200+行,评测的时候发现好像打次了!?跪惨。
std如下
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int SZ = 300010;
struct Plan
{
int u, v, lca, dis;
}p[SZ];
struct Edge
{
int f, t, d;
}es[SZ << 1];
int first[SZ << 1], nxt[SZ << 1], tot = 1, cnt;
int n, m, jump[SZ][30], dis[SZ], in[SZ];
int recover[SZ], cost[SZ], depth[SZ];
int u, v, w, TOT = 0, l, r, mid;
bool vis[SZ];
int read()
{
int f = 1, num = 0;
char c = getchar();
while(c < '0' || '9' < c)
{
if(c == '-') f = -1;
c = getchar();
}
while('0' <= c && c <= '9')
{
num = num * 10 + (c - '0');
c = getchar();
}
return num *= f;
}
inline void build(int ff, int tt, int dd)
{
es[++tot] = (Edge){ff, tt, dd};
nxt[tot] = first[ff];
first[ff] = tot;
es[++tot] = (Edge){tt, ff, dd};
nxt[tot] = first[tt];
first[tt] = tot;
}
inline void dfs(int u)
{
for(int i = 1; i <= 17; ++i)
jump[u][i] = jump[jump[u][i - 1]][i - 1];
vis[u] = 1;
in[++cnt] = u;
for(int i = first[u]; i; i = nxt[i])
{
int v = es[i].t;
if(vis[v]) continue;
jump[v][0] = u;
depth[v] = depth[u] + 1;
dis[v] = dis[u] + es[i].d;
cost[v] = es[i].d;
dfs(v);
}
}
int get_lca(int uu, int vv)
{
if(depth[uu] < depth[vv]) swap(uu, vv);
int t = depth[uu] - depth[vv];
for(int i = 0; i <= 17; ++i)
if((t >> i) & 1) uu = jump[uu][i];
for(int i = 17; i >= 0; --i)
if(jump[uu][i] != jump[vv][i])
uu = jump[uu][i], vv = jump[vv][i];
if(uu == vv) return uu;
return jump[uu][0];
}
bool check(int mid)
{
for(int i = 1; i <= n; ++i) recover[i] = 0;
int tot = 0, maxn = 0;
for(int i = 1; i <= m; ++i)
if(p[i].dis > mid)
{
++tot;
maxn = max(p[i].dis, maxn);
++recover[p[i].u]; ++recover[p[i].v]; recover[p[i].lca]-=2;
}
//else break;
if(!tot) return true;
for(int i = cnt; i > 1; --i) recover[jump[in[i]][0]] += recover[in[i]];
for(int i = 2; i <= n; ++i)
if(maxn - cost[i] <= mid && recover[i] == tot) return true;
return false;
}
int main()
{
int __size__ = 1024 << 15;
char * __p__ = (char *) malloc(__size__) + __size__;
__asm__("movl %0, %%esp\n" :: "r"(__p__));
freopen("foolish.in", "r", stdin);
freopen("foolish.out", "w", stdout);
n = read(); m = read();
for(int i = 1; i < n; ++i)
{
u = read(), v = read(), w = read();
build(u, v, w); TOT += w;
}
depth[1] = 1;
dfs(1);
for(int i = 1; i <= m; ++i)
{
p[i].u = read(); p[i].v = read();
//cout<<depth[p[i].u]<<" "<<depth[p[i].v]<<endl;
p[i].lca = get_lca(p[i].u, p[i].v);
p[i].dis = dis[p[i].u] + dis[p[i].v] - (dis[p[i].lca] << 1);
//cout<<p[i].lca<<endl;
}
l = 0, r = TOT;
while(l <= r)
{
mid = (l + r) >> 1;
if(check(mid)) r = mid - 1;
else l = mid + 1;
}
printf("%d", l);
fclose(stdin);
fclose(stdout);
return 0;
}
胡策以来跪的最惨的一次考试233,基本都是暴力分。
round 4
出题 by 天线 DL fluency a 帝江
考试时的cy:T1裸中余定,然而我不会,上暴力233,T2一模拟!?,瞎搞一搞,好像会有精度问题,T3sx题直接过,T4什么玩意,好像线段树能搞?拿线段树搞一搞。于是就有了T1暴力,T2翻车,T3AC,T4暴力的cy ╮(╯▽╰)╭。
T1
中国剩余定理Orz,不过还是暴力大法好233.
std如下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAXN=1000+10;
int a[MAXN],b[MAXN];
LL exgcd(LL a,LL b,LL &x,LL &y)//扩展欧几里得
{
if(b==0)
{
x=1;
y=0;
return a;
}
else
{
LL p=exgcd(b,a%b,x,y);
LL t=x;
x=y;
y=t-a/b*x;
return p;
}
}
/*x%a[i]==b[i]*/
LL China(int n)//中国剩余定理
{
LL M=1,d,x=0,y;
for(int i=1;i<=n;i++)
M*=(LL)a[i];
for(int i=1;i<=n;i++)
{
LL w=M/(LL)a[i];
exgcd(w,a[i],d,y);
x=(x+d*w*b[i])%M;
}
return (x+M)%M;
}
int main()
{
freopen("Question.in","r",stdin);
freopen("Question.ans","w",stdout);
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i],&b[i]);
printf("%lld\n",China(n));
return 0;
}
T2
确实就是一个模拟,不过我好像搞错了什么233,直接上代码
std如下
#include<cstdio>
#include<cmath>
#include<algorithm>
#define inf 598460606
#define LL long long
using namespace std;
int n,m,per=1;
int lt,ld,nt=1;
char ch[5];
double t[210000],d[210000],x,nowt;
int main()
{
freopen("dig.in","r",stdin);
freopen("dig.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%s%lf",ch,&x);
if (ch[0]=='T')t[++lt]=x;
else d[++ld]=x;
}
d[++ld]=0.0;
d[++ld]=m;
sort(d+1,d+ld+1);
sort(t+1,t+lt+1);
for(int i=1;i<ld;i++)
{
double nd=d[i];
while (nd<d[i+1]&&nt<=lt&&nowt+(d[i+1]-nd)*per>t[nt])
{
nd+=(t[nt]-nowt)/per;
per++;
nowt=t[nt++];
}
nowt+=(d[i+1]-nd)*per;
per++;
}
printf("%I64d\n",(long long)nowt);
}
T3
出题人好像是想要考代码细节处理?好多人都在这题上翻车了233,注意下并不只是判断最短路上是否存在负环就好吧。
代码如下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
const int size = 2001000;
int read()
{
int x = 0 , f = 1;
char in = getchar();
while(in < '0' || in > '9')
{
if(in == '-')
f = -1;
in = getchar();
}
while(in >= '0' && in <= '9')
{
x = x * 10 + in - '0';
in = getchar();
}
return x * f;
}
int head[size],nxt[size];
ll dist[size];
int tot = 1;
struct gtnd
{
int t;
ll d;
}l[size];
int n,m;
void build(int f,int t,int d)
{
l[tot].t = t;
l[tot].d = d;
nxt[tot] = head[f];
head[f] = tot ++;
}
queue < int > q;
bool use[size];
bool vis[size];
int tim[size];
void dfs(int u)
{
vis[u] = 1;
for(int i = head[u] ; i ; i = nxt[i])
if(!vis[l[i].t])
dfs(l[i].t);
}
void init()
{
while(!q.empty())
q.pop();
for(int i = 1 ; i <= n ; i ++)
dist[i] = 214748364111ll;
for(int i = 1 ; i <= n ; i ++)
tim[i] = 0;
}
bool spfa(int s)
{
init();
dist[s] = 0;
use[s] = 1;
q.push(s);
while(!q.empty())
{
int f = q.front();
q.pop();
use[f] = 0;
for(int i = head[f] ; i ; i = nxt[i])
{
int t = l[i].t;
if(dist[t] > dist[f] + l[i].d)
{
dist[t] = dist[f] + l[i].d;
tim[t] = tim[f] + 1;
if(tim[t] > 2 * n)
return false;
if(!use[t])
{
use[t] = 1;
q.push(t);
}
}
}
}
return true;
}
int main()
{
freopen("EasySSSP.in","r",stdin);
freopen("EasySSSP.out","w",stdout);
n = read() , m = read();
int s = read();
for(int i = 1 ; i <= m ; i ++)
{
int f = read() , t = read() , d = read();
build(f,t,d);
}
for(int i = 1 ; i <= n ; i ++)
{
if(!vis[i])
{
dfs(i);
if(!spfa(i))
{
puts("-1");
fclose(stdin);
fclose(stdout);
return 0;
}
}
}
spfa(s);
for(int i = 1 ; i <= n ; i ++)
{
if(dist[i] == 214748364111ll)
puts("NoPath");
else
printf("%lld\n",dist[i]);
}
fclose(stdin);
fclose(stdout);
return 0;
}
/*
5 5 1
1 2 1
2 1 1
3 4 2
4 5 -2
5 3 2
*/
T4
红太阳的题太强啦,只会暴力呀,乱搞大失败呀233,大体意思是分下块然后用set维护下?
std如下
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int f[300005],num[300005];
int mn[605],ans[300005];
int n;
char opt[100005];
int S[1000005],top;
int find(int i)
{
while(f[i]!=i)
{
S[++top]=i;
i=f[i];
}
while(top)
{
f[S[top]]=i;
top--;
}
return i;
}
int cnt[300005];
char s[5];
int main()
{
freopen("Math.in","r",stdin);
freopen("Math.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=300000;i++) f[i]=i+1;
memset(mn,127,sizeof(mn));
for (int i=1;i<=n;i++)
{
scanf("%s",s);
opt[i]=s[0];
scanf("%d",&num[i]);
if (opt[i]=='A')
{
for (int j=1;j<=540;j++) mn[j]=min(mn[j],num[i]%j);
f[num[i]]=num[i];cnt[num[i]]++;
}
else if (num[i]<=540) ans[i]=mn[num[i]];
}
for (int i=n;i;i--)
{
if (opt[i]=='A')
{
cnt[num[i]]--;
if(cnt[num[i]]==0)
f[num[i]]=f[num[i]+1];
}
else if(num[i]>540)
{
ans[i]=find(1)%num[i];
for (int j=num[i];j<=300000;j+=num[i])
{
int x=find(j);
if (x) ans[i]=min(ans[i],x%num[i]);
}
}
}
for (int i=1;i<=n;i++)
if (opt[i]=='B') printf("%d\n",ans[i]);
return 0;
}
round 5
出题 by ChlorineHikari,Yuan,Meico,Summer, (题目顺序)Peacefuldoge(后期)
最后的一次胡策,题目偏向模板。
考试时的cy : T1不就模拟吗233,T2一sx压位搜索,wocT3K短路然而我没学过A*,wocT4一树形DP然而我还是没学过╮(╯▽╰)╭。
T1
模拟搞一搞,据说是cf上的原题。
std如下
//Codeforces Round #375 (Div. 2) B
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=20000;
char hah[maxn];
int l[maxn];
int r[maxn];
int n;
int ans2=0;
void haha(int ll,int rr)
{
for(int i=ll+1;i<rr;)
{
if(hah[i]=='_')
i++;
else
{
ans2++;
while(hah[i]!='_'&&i<rr)
{
i++;
}
}
}
}
int main()
{
freopen("letter.in","r",stdin);
freopen("letter.osu","w",stdout);
int ans1=0;
scanf("%d",&n);
int lc=0;
int rc=0;
for(int i=1;i<=n;i++)
{
cin>>hah[i];
if(hah[i]=='(')
{
l[++lc]=i;
}
if(hah[i]==')')
{
r[++rc]=i;
}
}
for(int i=1;i<=n;)
{
if(hah[i]=='_')
{
i++;
}
else if(hah[i]=='(')
{
while(i<=n)
{
i++;
if(hah[i]==')')
break;
}
}
else
{
if(hah[i]==')')
i++;
int cnt=0;
while(hah[i]!='_'&&hah[i]!='('&&i<=n)
{
i++;
cnt++;
}
ans1=max(ans1,cnt);
}
}
for(int i=1;i<=lc;i++)
{
haha(l[i],r[i]);
}
cout<<ans1<<" ";
printf("%d",ans2);
return 0;
}
T2
经典的状压搜索问题,没啥好注意的。
代码如下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int sz = 1 << 11;
const int size = 214;
struct gtnd
{
int now;
int step;
};
int repair[size];
int destory[size];
int n,m;
queue < gtnd > q;
bool check(int x)
{
for(int i = 1 ; i <= n ; i ++)
if(!((x>>i) & (1)))
return false;
return true;
}
bool use[1000010];
/*
void print(int x)
{
for(int i = 1 ; i <= n ; i ++)
printf("%d ",(x >> i) & (1));
puts("");
}
*/
int bfs()
{
gtnd s;
s.now = 0;
s.step = 0;
use[s.now] = 1;
q.push(s);
while(!q.empty())
{
gtnd f = q.front();
q.pop();
if(check(f.now))
return f.step;
for(int i = 1 ; i <= m ; i ++)
{
gtnd nxt;
nxt.now = f.now;
nxt.now |= repair[i];
nxt.now &= (~destory[i]);
if(use[nxt.now] == 0)
{
use[nxt.now] = 1;
nxt.step = f.step + 1;
q.push(nxt);
}
}
}
return -1;
}
int main()
{
freopen("glgjssy.In","r",stdin);
freopen("glgjssy.0ut","w",stdout);
scanf("%d%d",&n,&m);
for(int i = 1 ; i <= m ; i ++)
{
for(int j = 1 ; j <= n ; j ++)
{
int ins;
scanf("%d",&ins);
if(ins == 1)
repair[i] |= 1 << j;
else if(ins == -1)
destory[i] |= 1 << j;
}
}
int ans = bfs();
if(ans == -1)
puts("GG");
else
printf("%d\n",ans);
fclose(stdin);
fclose(stdout);
return 0;
}
/*
3 2
1 0 1
-1 1 0
3 3
1 -1 -1
-1 1 -1
-1 -1 1
3 3
1 -1 0
0 1 -1
0 0 1
1 0 1 / 0 0 0
0 1 0 / 1 0 0
*/
T3
由于我对dij还A*都不感冒,考试的时候就打了个spfa求次短路糊弄了下233。
std如下
//POJ 2449 k短路
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int inf=0x7fffffff;
const int maxn=100000+500;
struct Edge
{
int to;
int d;
int next;
}edge[maxn],edge1[maxn];
int head[maxn],head1[maxn],h[maxn];
int n,m,ss,tt,k;
struct heap
{
int p;
int dis;
int h;
bool operator <(const heap &hah)const
{
return dis+h>hah.dis+hah.h;
}
};
priority_queue<heap>q;
int tott;
void add(int f,int t,int d)
{
edge[++tott].to=t;
edge[tott].d=d;
edge[tott].next=head[f];
head[f]=tott;
}
int tot1;
void add1(int f,int t,int d)
{
edge1[++tot1].to=t;
edge1[tot1].d=d;
edge1[tot1].next=head1[f];
head1[f]=tot1;
}
queue<int>q1;
bool vis[maxn];
void spfa()
{
for(int i=1;i<=n;i++)
h[i]=inf;
q1.push(tt);
h[tt]=0;
while(!q1.empty())
{
int x=q1.front();
vis[x]=0;
q1.pop();
for(int i=head1[x];i;i=edge1[i].next)
{
Edge e=edge1[i];
if(h[e.to]>h[x]+e.d)
{
h[e.to]=h[x]+e.d;
if(!vis[e.to])
{
vis[e.to]=1;
q1.push(e.to);
}
}
}
}
}
int ans=-1;
void DJ()
{
int cnt=0;
heap hah;
hah.p=ss;
hah.dis=0;
hah.h=h[ss];
q.push(hah);
while(!q.empty())
{
heap pre=q.top();
q.pop();
int x=pre.p;
if(x==tt)
{
cnt++;
if(cnt==k)
{
ans=pre.dis;
return;
}
}
for(int i=head[x];i;i=edge[i].next)
{
Edge e=edge[i];
q.push((heap){e.to,pre.dis+e.d,h[e.to]});
}
}
}
int main()
{
freopen("chemistry.in","r",stdin);
freopen("chemistry.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
add1(b,a,c);
}
scanf("%d%d%d",&ss,&tt,&k);
if(ss==tt)
k++;
spfa();
DJ();
printf("%d",ans);
return 0;
}
T4
原题codevs选课,多叉转二叉后跑下dp。
代码如下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int size = 1010;
const int sz = 200010;
int val[size];
int dist[size];
int r[size];
int len,n,m;
int head[sz],nxt[sz],l[sz];
int tot = 1;
bool use[size];
int f[size][size]; // f[i][j] 第 i 个节点
void build(int f,int t)
{
l[tot] = t;
nxt[tot] = head[f];
head[f] = tot ++;
}
struct gtnd
{
int l, r;
}tree[size];
queue < int > q;
int read()
{
int x = 0 , f = 1;
char in = getchar();
while(in < '0' || in > '9')
{
if(in == '-')
f = -1;
in = getchar();
}
while(in >= '0' && in <= '9')
{
x = (x << 3) + (x << 1) + in - '0';
in = getchar();
}
return x * f;
}
int dfs(int u,int pick)
{
if(!u)
return 0;
if(f[u][pick])
return f[u][pick];
for(int i = 0 ; i <= pick - 1 ; i ++)
f[u][pick] = max(f[u][pick],dfs(tree[u].l,i)+val[u]+dfs(tree[u].r,pick-i-1));
f[u][pick] = max(f[u][pick],dfs(tree[u].r,pick));
return f[u][pick];
}
int main()
{
freopen("dreamerpeacefuldoge.in","r",stdin);
freopen("dreamerpeacefuldoge.out","w",stdout);
n = read() , m = read();
for(int i = 1 ; i <= n ; i ++)
{
int par = read();
val[i] = read();
if(tree[par].l)
tree[i].r = tree[par].l;
tree[par].l = i;
}
printf("%d\n",dfs(tree[0].l,m));
fclose(stdin);
fclose(stdout);
return 0;
}
总结下,虽然我不怎么会总结
看到学弟(妹)们越来越套路我还是很滋磁的233,大家noip加油吧233。
All Loiers rp ++;