这里是noip2017蒟蒻考后感……
D1T1小凯的疑惑
考场是用模拟写的,冗长的代码,拿了60分……
#include<bits/stdc++.h>
using namespace std;
const int p=100000;
long long a,b,sum,last,ans,t1,t2,head1=1,tail1=1,head2=1,tail2=1;
long long q1[100010],q2[100010];
long long read(){
long long num=0;char c=getchar();
for(;c<'0'||c>'9';c=getchar());
for(;c>='0'&&c<='9';c=getchar())
num=(num<<3)+(num<<1)+c-48;
return num;
}
void print(long long x){
if(x>9)print(x/10);
putchar(x%10+48);
}
void work(){
a=read();b=read();
if(a==1||b==1){
putchar('0');
exit(0);
}
if(a>b)swap(a,b);
long long k=min(b-a,a);
sum=0;last=-1;q1[1]=q2[1]=0;
head1=tail1=head2=tail2=1;
while(sum<k){
t1=q1[head1];t2=q2[head2];
++tail1;if(tail1>p)tail1-=p;
++tail2;if(tail2>p)tail2-=p;
if(t1<t2){
++head1;if(head1>p)head1-=p;
q1[tail1]=t1+a;
q2[tail2]=t1+b;
if(t1==last+1)
++sum,++last;
else
sum=1,last=t1;
}else if(t1>t2){
++head2;if(head2>p)head2-=p;
q1[tail1]=t2+a;
q2[tail2]=t2+b;
if(t2==last+1)
++sum,++last;
else
sum=1,last=t2;
}else{
++head1;++head2;
if(head1>p)head1-=p;if(head2>p)head2-=p;
q1[tail1]=t1+a;
q2[tail2]=t1+b;
if(t1==last+1)
++sum,++last;
else
sum=1,last=t1;
}
}
ans=last-k+1;
while(k<a){
ans+=a;
k+=b-a;
}
print(ans-1);
}
int main(){
work();
return 0;
}
那么正解就是—— a×b−a−b ……
#include<bits/stdc++.h>
using namespace std;
long long a,b,c=0;
int main(){
scanf("%lld%lld",&a,&b);
c=a*b-a-b;
printf("%lld",c);
return 0;
}
别说了吧,要落泪了。
D1T2时间复杂度
一个大模拟题,考场上少想了一点,就被卡掉一个点……
直接贴正解吧。
#include<bits/stdc++.h>
using namespace std;
struct ty{
int f,id,in;
}st[1010];//一个栈,f存这个循环的复杂度贡献,id是为了方便存储
char temp[20];//为了解决字符读入的问题
int now,top,t,l,fuza,sum[1010],flag[30];
int read(){
int num=0;char c=getchar();
for(;c<'0'||c>'9';c=getchar());
for(;c>='0'&&c<='9';c=getchar())
num=(num<<3)+(num<<1)+c-48;
return num;
}
void end(int x){
for(int i=x;i<=l;++i)
gets(temp);//ERR后直接读完
printf("ERR\n");
}
void first(){
memset(sum,0,sizeof(sum));
memset(flag,0,sizeof(flag));
l=read();
char c=getchar();
for(;c!='(';c=getchar());
c=getchar();
if(c=='n')fuza=read();
else fuza=0;//读入给定的复杂度
gets(temp);
}
void work(){
st[0].f=0;st[0].id=0;top=0;
for(int i=1;i<=l;++i){
char c=getchar();
if(c=='F'){
c=getchar();
c=getchar();
now=c-'a';
if(flag[now]){//如果变量名被用过
end(i);
return;
}
flag[now]=1;
st[++top].in=now;
st[top].id=i;
c=getchar();c=getchar();
if(c=='n'){
c=getchar();c=getchar();
if(c=='n')st[top].f=0;//n~n,0表示常数复杂度
else st[top].f=-1;//n~1,-1表示该循环不执行
}else{
int x=0;
for(;c>='0'&&c<='9';c=getchar())x=x*10+c-48;
c=getchar();
if(c=='n')st[top].f=1;//1~n,贡献一重的复杂度
else{
int y=0;
for(;c>='0'&&c<='9';c=getchar())y=y*10+c-48;
if(x<=y)st[top].f=0;//1~1,常数
else st[top].f=-1;//2~1,不执行
continue;
}
}
}else{//要结束循环
if(!top){//如果栈空
end(i);
return;
}
flag[st[top].in]=0;
if(st[top].f!=-1)//当前循环执行
sum[st[top-1].id]=
max(sum[st[top-1].id],sum[st[top].id]+st[top].f);//计算复杂度,max防止一个循环里有并列的多个循环
--top;
}
gets(temp);//很重要的读入
}
if(top>0){//仍有循环未结束
printf("ERR\n");//这里不用调用end()哟
return;
}
if(sum[0]==fuza)printf("Yes\n");//top[0].id=0,所以最后的复杂度会在sum[0]中
else printf("No\n");
}
void init(){
t=read();
for(int i=1;i<=t;++i){
first();
work();
}
}
int main(){
init();
return 0;
}
D1T3逛公园
蒟蒻在考场放弃了这题……
正解待学习。
D2T1奶酪
这题还是很T1的,建图然后bfs搞一下,就AC了。
听说unsigned long long绝对不会爆炸,但是由于我的玄学判断,long long成功过关。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1010,MAXM=1000010;
struct line{
int b,next;
}l[MAXM];
int t,n,sum=0,head,tail,q[MAXN],fi[MAXN],f[MAXN];
long long h,r,x[MAXN],y[MAXN],z[MAXN];
int read(){
int num=0,flag=1;char c=getchar();
for(;c<'0'||c>'9';c=getchar())if(c=='-')flag=-1;
for(;c>='0'&&c<='9';c=getchar())
num=(num<<3)+(num<<1)+c-48;
return num*flag;
}
long long read_(){
long long num=0,flag=1;char c=getchar();
for(;c<'0'||c>'9';c=getchar())if(c=='-')flag=-1;
for(;c>='0'&&c<='9';c=getchar())
num=(num<<3)+(num<<1)+c-48;
return num*flag;
}
void make_line(int i,int j){
l[++sum].b=j;l[sum].next=fi[i];fi[i]=sum;
l[++sum].b=i;l[sum].next=fi[j];fi[j]=sum;
}
bool check(int i,int j){
long long tempx,tempy,tempz;
tempx=abs(x[i]-x[j]);
tempy=abs(y[i]-y[j]);
tempz=abs(z[i]-z[j]);
if(tempz>2*r||tempy>2*r||tempz>2*r)return false;//一点点的小优化,防止乘法爆long long
long long temp=tempx*tempx+tempy*tempy+tempz*tempz;
if(temp<=1LL*4*r*r)return true;
return false;
}
void work(){
memset(fi,0,sizeof(fi));
n=read();h=read_();r=read_();sum=0;
for(int i=1;i<=n;++i){
x[i]=read_();y[i]=read_();z[i]=read_();
}
for(int i=1;i<=n;++i){
if(abs(z[i])<=r)make_line(0,i);
if(abs(h-z[i])<=r)make_line(i,n+1);//上下表面建图
for(int j=i+1;j<=n;++j)
if(check(i,j))make_line(i,j);//奶酪内建图
}
memset(f,0,sizeof(f));
f[0]=1;
head=1,tail=1,q[1]=0;
while(head<=tail){//bfs
int u=q[head];
for(int i=fi[u];i;i=l[i].next){
int v=l[i].b;
if(!f[v]){
f[v]=1;
q[++tail]=v;
}
if(v==n+1){
printf("Yes\n");
return;
}
}
++head;
}
printf("No\n");
}
int main(){
t=read();
for(int i=1;i<=t;++i)
work();
return 0;
}
D2T2宝藏
这题一看数据范围就想到了去年的状压dp,一开始写错了,后来调出个80分……
我的愚蠢的代码就不放了。
正解待添加。
2017 12 17update
发现我的代码其实是可以过noip的数据的???
只是数组范围又双叒叕开小了????
我* * * *
#include<bits/stdc++.h>
using namespace std;
const int INF=40000000;
struct line{
int y,next,w;
}l[15];
int n,m,ans=40000000,maxx=0,x,y,v,sum;
int f[13][4100],now[13][4100][13]={};//就是这里写成了12……
int d[15][15],deep[15],fi[15],val[15];
int read(){
int num=0,flag=1;char c=getchar();
for(;c<'0'||c>'9';c=getchar())if(c=='-')flag=-1;
for(;c>='0'&&c<='9';c=getchar())
num=(num<<3)+(num<<1)+c-48;
return num*flag;
}
void dfs(int b,int s){
if(f[b][s]<INF)return;
for(int i=1;i<=n;++i)
if((1<<(i-1)&s)&&i!=b){
int t=s-(1<<(i-1));
dfs(b,t);
for(int j=1;j<=n;++j)
if((1<<(j-1)&t)&&d[j][i]!=-1)
if(f[b][t]+d[j][i]*now[b][t][j]<f[b][s]){
f[b][s]=f[b][t]+d[j][i]*now[b][t][j];
now[b][s][i]=now[b][t][j]+1;
for(int k=1;k<=n;++k)
if(k!=i)now[b][s][k]=now[b][t][k];
}
}
if(s==maxx)ans=min(ans,f[b][s]);
}
void work(int b){
f[b][1<<(b-1)]=0;
for(int i=0;i<=maxx;++i)now[b][i][b]=1;
for(int i=1;i<=n;++i)
if(i!=b&&d[b][i]!=-1){
f[b][(1<<(i-1))+(1<<(b-1))]=d[b][i];
now[b][(1<<(i-1))+(1<<(b-1))][i]=2;
}
dfs(b,maxx);
return;
}
void make_line(int i,int j,int w){
l[++sum].y=j;l[sum].next=fi[i];fi[i]=sum;l[sum].w=w;
l[++sum].y=i;l[sum].next=fi[j];fi[j]=sum;l[sum].w=w;
}
void dfs_tree(int x,int fa){
deep[x]=deep[fa]+1;
for(int i=fi[x];i;i=l[i].next){
int v=l[i].y;
if(v!=fa){
val[v]=l[i].w;
dfs_tree(v,x);
}
}
}
void work_1(){
for(int i=1;i<n;++i){
x=read();y=read();v=read();
make_line(x,y,v);
}
for(int i=1;i<=n;++i){
val[i]=0;
dfs_tree(i,0);
int temp=0;
for(int j=1;j<=n;++j)
temp+=(deep[j]-1)*val[j];
ans=min(ans,temp);
}
printf("%d\n",ans);
exit(0);
}
void init(){
memset(d,-1,sizeof(d));
memset(f,10,sizeof(f));
n=read();m=read();
if(m==n-1)work_1();
for(int i=1;i<=m;++i){
x=read();y=read();v=read();
if(d[x][y]!=-1)
d[x][y]=d[y][x]=min(d[x][y],v);
else d[x][y]=d[y][x]=v;
}
for(int i=0;i<n;++i)maxx+=(1<<i);
for(int i=1;i<=n;++i)work(i);
printf("%d\n",ans);
}
int main(){
init();
return 0;
}
D2T3列队
考场果断选择30分……
正解是并不会的树状数组……
那么就……待添加。