-------------------题目难度较难,但挺有营养的。慢慢补。

A .ASCII Addition

pro:用一定的形式表示1到9,让你计算加法。

sol:模拟。

solved by fzl;

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
typedef long long ll;
string s[] =
{
"xxxxxx...xx...xx...xx...xx...xxxxxx",
"....x....x....x....x....x....x....x",
"xxxxx....x....xxxxxxx....x....xxxxx",
"xxxxx....x....xxxxxx....x....xxxxxx",
"x...xx...xx...xxxxxx....x....x....x",
"xxxxxx....x....xxxxx....x....xxxxxx",
"xxxxxx....x....xxxxxx...xx...xxxxxx",
"xxxxx....x....x....x....x....x....x",
"xxxxxx...xx...xxxxxxx...xx...xxxxxx",
"xxxxxx...xx...xxxxxx....x....xxxxxx",
".......x....x..xxxxx..x....x......."
};
char Map[][];
int judge(int x)
{
string tmp;
for(int i = ; i < ; i++)
for(int j = x; j < x + ; j++)tmp += Map[i][j];
for(int i = ; i <= ; i++)if(s[i] == tmp)return i;
}
int main()
{
for(int i = ; i < ; i++)cin >> Map[i];
int n = strlen(Map[]);
ll cnt = , a;
for(int i = ; i < n; i += )
{
int tmp = judge(i);
if(tmp == ){a = cnt;cnt = ;continue;}
cnt = cnt * + tmp;
}
a = a + cnt;
stringstream ss;string tmp;
ss << a;
ss >> tmp;
for(int i = ; i < ; i++)for(int j = ; j < tmp.size(); j++)
{
for(int k = * i; k < * i + ; k++)cout<<s[tmp[j] - ''][k];
if(j == tmp.size() - )cout<<endl;
else cout<<".";
}
return ;
}

B .Book Borders

pro:给定文本,假设每行最多放L个字母时,统计第一行的信息。

sol:模拟+二分即可。

solve by pb。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
string s[];
int a,b,cnt,ans,n,sum[];
template<class T>
inline void read(T&a){
char c=getchar();
for(a=;(c<''||c>'')&&c!='-';c=getchar());
bool f=;if(c=='-')f=,c=getchar();
for(;c>=''&&c<='';c=getchar())a=a*+c-'';
if(f)a=-a;
}
int main(){
ios::sync_with_stdio(false);
while(cin.peek()!='\n')cin>>s[++n],sum[n]=sum[n-]+s[n].size();
cin>>a>>b;
for(int i=a;i<=b;i++){
int las=,mid,l,r,now,hang=;
ans=;
while(las<n){
l=las+,r=n;
while(l<=r){
mid=(l+r)>>;
if(sum[mid]-sum[las]+mid-las-<=i)now=mid,l=mid+;
else r=mid-;
}
ans+=s[las+].size();
las=now;hang++;
}
printf("%d\n",ans+hang-);
}
return ;
}

D .Digit Division

pro:给定一个数字串,让你切割,使得切割后的每一部分都是M的倍数。

sol:保存前面切割的方案数,dp即可。 没mod 1e9+7,wa了一发。

solve by fcy。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
const int Mod=1e9+;;
ll ans,mp; char c[maxn];
int main()
{
mp=;
int N,M,x=;
scanf("%d%d%s",&N,&M,c+);
rep(i,,N){
x=x*+c[i]-''; x%=M;
if(x==) ans=mp,(mp+=mp)%=Mod;
else ans=;
}
printf("%lld\n",ans%Mod);
return ;
}

F.Frightful Formula

pro:给定N*N矩阵,给出第一行第一列的初始值 f[i][1]和f[1][i],其他位置的满足f[i][j]=a*f[i][j-1]+b*f[i-1][j]+c;  求f[N][N];

sol:如果没有c,此题直接组合数可以做,但是有c,可能要fft或者其他多项式的算法。 比较麻烦。

我们可以想办法把c去掉,不过数学渣fcy好像不会,只能参考别人的。 待定系数法很好的解决了这个问题。

参考:https://blog.csdn.net/liufengwei1/article/details/78271574

H .Hovering Hornet

pro:三维平面里,给定一个5*5*5的立方体,内部含有一个1*1*1的骰子,现在有一只蜜蜂,问它看到的点数和的期望。

sol:由于二者都是处于水平位置,所以看到上面的点的概率是一定的。 而周围4个点的概率取决于底面的面积,直接用半平面交即可。

updated by fcy。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
const double eps=1e-;
struct point{
double x,y;
point(){}
point(double xx,double yy):x(xx),y(yy){}
};
struct line{
point a;//起点
point p;//起点到终点的向量
line(){}
line(point aa,point pp):a(aa),p(pp){}
double angle;
};
double dot(point a,point b){ return a.x*b.x+a.y*b.y;}
double det(point a,point b){ return a.x*b.y-a.y*b.x;}
point operator *(point A,double p){ return point(A.x*p,A.y*p);}
point operator +(point A,point B){return point(A.x+B.x,A.y+B.y);}
point operator -(point A,point B){return point(A.x-B.x,A.y-B.y);}
double getangle(point a){ return atan2(a.y,a.x);}
double getangle(line a){ return getangle(a.p);}
point llintersect(line A,line B)
{
point C=A.a-B.a;
double t=det(C,B.p)/det(B.p,A.p);
return A.a+A.p*t;
}
point s[maxn]; line t[maxn],q[maxn]; int head,tail;
bool cmp(line a,line b){
double A=getangle(a),B=getangle(b);
point t=(b.a+b.p)-a.a;
if(fabs(A-B)<eps) return det(a.p,t)>0.0;
return A<B;
}
bool onright(line P,line a,line b)
{
point o=llintersect(a,b);
point Q=o-P.a;
return det(Q,P.p)>; //如果同一直线上不能相互看到,则>=0
}
point w[maxn]; int pcnt=;
double halfplaneintersect(int N,line p)
{
s[N+]=s[];
rep(i,,N) t[i].a=s[i],t[i].p=s[i+]-s[i];
t[++N]=p;
sort(t+,t+N+,cmp);
int tot=;
rep(i,,N-) {
if(fabs(getangle(t[i])-getangle(t[i+]))>eps)
t[++tot]=t[i];
}
t[++tot]=t[N]; head=tail=;
rep(i,,tot){
while(tail>head+&&onright(t[i],q[tail],q[tail-])) tail--;
while(tail>head+&&onright(t[i],q[head+],q[head+])) head++;
q[++tail]=t[i];
}
while(tail>head+&&onright(t[head+],q[tail],q[tail-])) tail--;
//while(tail>head+1&&onright(t[tail],q[head+1],q[head+2])) head++;加上了会wa6,不知道为什么
pcnt=; q[tail+]=q[head+];
rep(i,head+,tail) w[++pcnt]=llintersect(q[i],q[i+]);
double res=;
rep(i,,pcnt-) res+=det(w[i]-w[],w[i+]-w[]);
return res/;
}
void solve()
{
double ans=,area=5.0**-**;
rep(i,,) scanf("%lf%lf",&s[i].x,&s[i].y);
ans+=6.0*halfplaneintersect(,line(point(-0.5,0.5),point(,)))*/area;
ans+=5.0***/area;
ans+=4.0*halfplaneintersect(,line(point(-0.5,-0.5),point(,)))*/area;
ans+=3.0*halfplaneintersect(,line(point(0.5,0.5),point(,-)))*/area;
ans+=1.0*halfplaneintersect(,line(point(0.5,-0.5),point(-,)))*/area;
printf("%.10lf\n",ans);
}
int main()
{
solve();
return ;
}

I .Ice Igloos

pro:在500*500的二维平面上,给定N个圆。Q次询问,每次给出一个线段,问多少个圆和直线有交点。 N,Q<1e5

sol:由于平面并不大,所以我们可以暴力一点的做法。 即去找可能有交点是位置,然后看那个位置上的圆是否满足。

solved by fcy 我的做法是,枚举x坐标,然后求出这个x到直线最近的点,然后往两边找,复杂度~500*Q*常数。(比标程暴力一丢丢)

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
double G[][];
struct point{
double x,y;
point(){}
point(double xx,double yy):x(xx),y(yy){}
}A,B;
double det(point a,point b) {return a.x*b.y-a.y*b.x;}
double dot(point a,point b) {return a.x*b.x+a.y*b.y;}
double dist(point a,point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double ptoseg(point p)
{
point Ap=point(p.x-A.x,p.y-A.y);
point AB=point(B.x-A.x,B.y-A.y);
point pB=point(B.x-p.x,B.y-p.y);
if(dot(AB,Ap)<=) return dist(A,p);
if(dot(AB,pB)<=) return dist(B,p);
return fabs(det(Ap,AB)/dist(A,B));
}
int ans;
void get1(int x,int y)
{
while(y>=){
double ty=1.0*y;
double dis=ptoseg(point(1.0*x,ty));
if(dis>1.0) break;
if(G[x][y]>dis) ans++;
y--;
}
}
void get2(int x,int y)
{
while(y<=){
double ty=1.0*y;
double dis=ptoseg(point(1.0*x,ty));
if(dis>1.0) break;
if(G[x][y]>dis) ans++;
y++;
}
}
int main()
{
int N,Q;
scanf("%d",&N);
rep(i,,N){
int x,y; double r;
scanf("%d%d%lf",&x,&y,&r);
G[x][y]=r;
}
scanf("%d",&Q);
while(Q--){
scanf("%lf%lf%lf%lf",&A.x,&A.y,&B.x,&B.y);
if(A.x>B.x||(A.x==B.x&&A.y>B.y)) swap(A.x,B.x),swap(A.y,B.y); ans=;
if(A.x==B.x){
for(int i=(int)A.y;i<=(int)B.y;i++)
ans+=(G[(int)A.x][i]>);
}
else if(A.y==B.y){
for(int i=(int)A.x;i<=(int)B.x;i++)
ans+=(G[i][(int)A.y]>);
}
else {
for(int i=max((int)A.x-,);i<=min((int)B.x+,);i+=){
double y=1.0*A.y;
if(i!=A.x) y=A.y+1.0*(B.y-A.y)/(B.x-A.x)*(i-A.x);
int t=(int)y;
get1(i,t);
get2(i,t+);
}
}
printf("%d\n",ans);
}
return ;
}

J .Juice Junctions

pro:给定N点M边的无向图,保证没个点的度数不超过3。 现在求所有点对的最大流。N<3e3, M<4.5e3;

sol:开始以为是N*M的复杂度,枚举起点,然后dfs,发现由于方向不能确定,所有并不能实现。

updated by fcy。

由于度数<=3;所以我们枚举点对,然后去验证可能性(0,1,2,3)。

0:不连通;    1:连通;   2: 双连通; 3:删去任意一边任然是双连通。

0,1用并查集可以做; 2用tarjan做。 3的话,需要用点东西才行,std的做法是,枚举删去的边,然后保存所有点所在的scc,所以两个点的所有情况下scc都同,即满足,这里可以用hash做。

#include<bits/stdc++.h>
#define ll unsigned long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
const int seed1=;
const int seed2=;
int Laxt[maxn],Next[maxn],To[maxn],cnt=;
int q[maxn],top,dfn[maxn],low[maxn],scc[maxn],scc_cnt,times;
int fa[maxn],ans,del,hash1[maxn],hash2[maxn];
void add(int u,int v)
{
Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v;
}
int find(int x)
{
if(x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
void dfs(int u,int f)
{
q[++top]=u; dfn[u]=low[u]=++times;
for(int i=Laxt[u];i;i=Next[i]){
if(i==del*||i==del*+||To[i]==f) continue;
if(!dfn[To[i]]) {
dfs(To[i],u);
low[u]=min(low[u],low[To[i]]);
}
else low[u]=min(low[u],dfn[To[i]]);
}
if(dfn[u]==low[u]){
scc_cnt++;
while(){
int x=q[top--];
scc[x]=scc_cnt;
if(x==u) break;
}
}
}
int main()
{
int N,M,u,v;
scanf("%d%d",&N,&M);
rep(i,,N) fa[i]=i;
rep(i,,M){
scanf("%d%d",&u,&v);
fa[find(u)]=find(v);
add(u,v); add(v,u);
}
rep(i,,N)
rep(j,i+,N)
if(find(i)==find(j)) ans++; rep(i,,N)
if(!dfn[i]) dfs(i,); rep(i,,N)
rep(j,i+,N)
if(scc[i]==scc[j]) ans++; rep(i,,M) {
del=i; scc_cnt=; times=;
rep(j,,N) dfn[j]=scc[j]=;
rep(j,,N) if(!dfn[j]) dfs(j,);
rep(j,,N){
hash1[j]=hash1[j]*seed1+scc[j];
hash2[j]=hash2[j]*seed2+scc[j];
}
}
rep(i,,N)
rep(j,i+,N) if(hash1[i]==hash1[j]&&hash2[i]==hash2[j]) ans++;
printf("%d\n",ans);
return ;
}

K .Kernel Knights

pro:给定二分图。每个点有个出度,现在让你找一种方案,选出其中一些点S,满足这些点之间没有边,而未选的点,至少有S中的点指向它,保证有解。

sol:首先,如果一个点没有入度,必选。 我们可以用topo排序得到这些点。 对于剩下的点,由于是二分图,我们选择其中一边即可。

solve by fzl&pb

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
typedef long long ll;
int n,a[],du[];
queue<int>que;
bool s[],c[];
void dfs(int x,int y){
if(y){
c[x]=;
if(!s[a[x]]&&!c[a[x]])dfs(a[x],);
}
else{
s[x]=;
if(!s[a[x]]&&!c[a[x]])dfs(a[x],);
}
}
int main(){
//freopen("1.in", "r", stdin);
//freopen("1.out", "w", stdout);
scanf("%d",&n);
for(int i=;i<=*n;i++){
scanf("%d",a+i);
du[a[i]]++;
}
for(int i=;i<=*n;i++)
if(!du[i])que.push(i);
while(!que.empty()){
int x=que.front();que.pop();
//cout<<x<<" "<<c[x]<<endl;
if(c[x])continue;du[a[x]]--;
s[x]=;
if(!c[a[x]])c[a[x]]=,du[a[a[x]]]--;
if(!s[a[a[x]]] && !c[a[a[x]]] && !du[a[a[x]]])que.push(a[a[x]]);
}
for(int i=;i<=*n;i++)
if(!s[i]&&!c[i])dfs(i,);
for(int i=;i<=*n;i++)
if(s[i])printf("%d ",i);
return ;
}

Gym - 101480 CERC 15:部分题目题解(队内第N次训练)的更多相关文章

  1. Gym101002 2016NAIPC(队内第7次训练)

    (由于先看的最后一题,然后又一直WA,导致这场有点爆炸,我背锅. A .Fancy Antiques 题意: 选择最多k个商店,买n个物品,每个物品分别对应两个店售卖,求最小花费是多少.n<10 ...

  2. Gym101485: NWERC 2015(队内第6次训练)

    A .Assigning Workstations 题意:给定N个人的工作时间和工作时长,我们可以假设有无数台工作机器,如果一台机器超过M时间未使用就会关闭,那么我们怎么安排机器的使用,使得需要开启机 ...

  3. PTA|团体程序设计天梯赛-练习题目题解锦集(C/C++)(持续更新中……)

    PTA|团体程序设计天梯赛-练习题目题解锦集(持续更新中) 实现语言:C/C++:      欢迎各位看官交流讨论.指导题解错误:或者分享更快的方法!! 题目链接:https://pintia.cn/ ...

  4. ZROI 部分题目题解

    ZROI 部分题目题解 335 首先发现一个性质: 对于最短的边而言,所有点的路径如果经过了这条边,那么路径的权值就是这条边的边权(废话) 那么我们把最短的边拎出来,可以发现,博物馆确定时,每个点按照 ...

  5. 【 Gym - 101138D 】Strange Queries (莫队算法)

    BUPT2017 wintertraining(15) #4B Gym - 101138D 题意 a数组大小为n.(1 ≤ n ≤ 50 000) (1 ≤ q ≤ 50 000)(1 ≤ ai ≤  ...

  6. LuoguB2001 入门测试题目 题解

    Update \(\texttt{2021.7.3}\) 经测试,本题 \(a,b\) 范围在 long long,对代码进行了修改,并修改一些笔误,更新了数据范围. \(\texttt{2021.7 ...

  7. chd校内选拔赛题目+题解

    题目链接   A. Currency System in Geraldion 有1时,所有大于等于1的数都可由1组成.没有1时,最小不幸的数就是1. #include<iostream> ...

  8. Tarjan & LCA 套题题目题解

    刷题之前来几套LCA的末班 对于题目 HDU 2586 How far away 2份在线模板第一份倍增,倍增还是比较好理解的 #include <map> #include <se ...

  9. cogs 自己出的题目 题解报告

    第一题很简单嘛,就是裸的动态树分治嘛 对于每一层的重心维护子树路径的信息和子树到上一层重心的点的信息 空间复杂度O(nlogn) 对于每一层我们按dis排序,之后记录军队数量的前缀和 查询的时候我们只 ...

随机推荐

  1. notepad++自动对齐使用空格代替Tab并将空格显示为小点

    一.说明 对大多数语言而言自动对齐使用空格还是tab对编译运行并没有什么影响,但对python问题就很大:因为就算是缩进看起来是一样的但某些行用空格某些行用tab运行会报错. 另外除了空格替换tab外 ...

  2. 运维相关 docker

  3. 使用Swagger2构建强大的RESTful API文档(2)(二十三)

    添加文档内容 在完成了上述配置后,其实已经可以生产文档内容,但是这样的文档主要针对请求本身,而描述主要来源于函数等命名产生,对用户并不友好,我们通常需要自己增加一些说明来丰富文档内容.如下所示,我们通 ...

  4. vim 文本会在末尾自动添加换行 md5文件和数据只不对应

    在linux系统 vim md5data  # 打开文件 写入 abc 保存 md5sum md5Data  的计算值和openssl代码计算值不一样 原因在于linux文本文件末尾自动添加了换行 解 ...

  5. python 内置函数源码查看

    如果是用python 实现的模块可以直接在IDE里面追踪到源码 也可以使用help内置函数,例如: help(os) 如果是c 语言实现的模块,则不能直接在IDE里面查看,如果直接在IDE里面查看,会 ...

  6. 1-4Controller之Middleware

    1.注册中间件: 新建中间件文件:Activity <?php namespace App\Http\Middleware; use Closure; class Activity{ publi ...

  7. laravel composer 安装指定版本以及基本的配置

    1 安装指定的 laravel版本 以下的案例是安装5.2版本 composer create-project laravel/laravel=5.2.* --prefer-dist 2 配置 优化相 ...

  8. markdown语法模板

    (GitHub-Flavored) Markdown Editor Basic useful feature list: Ctrl+S / Cmd+S to save the file Ctrl+Sh ...

  9. sqlalchemy动态组合查询语句。

    if filter_type == 1: search = and_(GameRoom.status ==1,or_( and_(GameRoom.white_user_id == user_id, ...

  10. leetcode python 003

    ## 给定一个字符串,求其最长无重复的子字符串##给定“abcabcbb”,答案是“abc”,长度为3.##给定“bbbbb”,答案是“b”,长度为1.##鉴于“pwwkew”,答案是“wke”,长度 ...