SDOI-07-DAY2

SDOI-07-DAY2

昨天晚上做了一下,结果真的被虐爆了,考完之后毫无感觉,直接睡觉。。。
第一题超恶心,不仅要输出结果还要输出方案,打了半个小时草稿,
连计算方案的算法也没搞出来,只以为是搜索了,但因为后面两天没时间写了。。。
最后手算1~16输出,10分。。。
第二题:二进制的高精度Stein算法,一开始以为数字只会变小,就按照读入顺序存的
结果挂掉。。重写,因各种原因挂掉。。50
第三题,并查集,做过的,AC。
结果160,勉强第四。
如果第三题没有做过,就要100-,10+了。。。
PS:神奇地发现总分上升到第二。。。几个只会做水题的同学悲剧了。可以见得,多试对于选拔选手是有一定好处的。

好吧,总结一下。
首先是考试策略问题。
第一题的确是搜索,裸的ID-DFS就可以AC(写了不超过10分钟。。),完全不需要数学方法。。。
当然我看到了一个比我的程序10多倍的搜索程序,正在研究中。
 
裸的ID-DFS
#include<cstdio>
#include
<bitset>
#include
<cstring>
#include
<iostream>
#include
<fstream>
#include
<algorithm>
    
using namespace std;
#define MM(a,i) memset(a,i,sizeof(a))
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define NFOR(i,a,b) for(i=a;i<=b;i++)
#define DFOR(i,b,a) for(int i=b;i>=a;i--)
#define NDFOR(i,b,a) for(i=b;i>=a;i--)
#define PFOR(p,head,next) for(int p=head;p;p=next[p])
#define NPFOR(p,head,next) for(p=head;p;p=next[p])
    
int ans[16],depth,n,p;
    
void dfs(int i);
    ifstream fin(
"shulie.in");
    ofstream fout(
"shulie.out");
    
int main(){
        fin
>>n;
        NFOR(depth,
1,15)p=ans[1]=1,dfs(2);
        }

    
void dfs(int i){
        
if(ans[p]==n){
            fout
<<p<<"\n";
            FOR(i,
1,p-1)fout<<ans[i]<<" ";
            fout
<<n,exit(0);
            }

        
if(i>depth)return;
        DFOR(k,p,
1)//下一项是由最后一项和前p项中的任意一项构成的,易证其正确性 
            p++,ans[p]=ans[p-1]+ans[k],dfs(i+1),p--;
        }



快我10的代码(pas)
program shulie;
var
a:array[
1..20] of longint;
i,j,k,n:longint;

procedure CloseFile;
begin
close(input); close(output); halt;
end;

procedure dfs(step:longint);
var
i,j:longint;
begin
for i:=step-1 downto 1 do
for j:=step-1 downto i do
begin
a[step]:
=a[i]+a[j];
if a[step]>n then continue;
if (a[step]<a[step-1]) or (a[step] shl (k-step)<n) then break;
if a[step]=n then
begin
writeln(k);
for k:=1 to step-1 do
write(a[k],
' ');
writeln(a[step]);
CloseFile;
end;
if step<k then dfs(step+1);
end;
end;

begin
assign(input,
'shulie.in'); reset(input);
assign(output,
'shulie.out'); rewrite(output);
readln(n);
case n of
1:begin
writeln(
1); writeln(1); CloseFile;
end;
2:begin
writeln(
2); writeln(1,' ',2); CloseFile;
end;
end;
k:
=2; a[1]:=1; a[2]:=2;
repeat
inc(k); dfs(
3);
until
false;
end.

第二题,一者是算法不全面(有可能就是错的),使代码过长。
            二者比较函数,写错了。。。
stein算法核心代码:
        int t=equal(a,b);
        if(t==2){gcd(b,a);return;}
        else if(t==0){copy(ans,b);return;}
        if(b[0]==1&&b[1]==1){copy(ans,b);return;}
        if((b[0]==1||b[0]==0)&&b[1]==0){copy(ans,a);return;}
        //
        if(!(b[1]&1)&&!(a[1]&1)){div2(a),div2(b),gcd(a,b),tim2(ans);return;}
        if((b[1]&1)&&(a[1]&1)){sub(a,b),gcd(a,b);return;}
         //这一类有两种方法gcd(a,b)=gcd((a+b)/2,(a-b)/2)  或 gcd(a,b)=gcd(a-b,b)实现起来差距巨大
        if(!(b[1]&1)&&(a[1]&1)){div2(b),gcd(a,b);return;}
        if((b[1]&1)&&!(a[1]&1)){div2(a),gcd(a,b);return;}
完整代码
#include<cstdio>
#include
<bitset>
#include
<cstring>
#include
<iostream>
#include
<fstream>
#include
<algorithm>
using namespace std;
#define MM(a,i) memset(a,i,sizeof(a))
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define NFOR(i,a,b) for(i=a;i<=b;i++)
#define DFOR(i,b,a) for(int i=b;i>=a;i--)
#define NDFOR(i,b,a) for(i=b;i>=a;i--)
#define PFOR(p,head,next) for(int p=head;p;p=next[p])
#define NPFOR(p,head,next) for(p=head;p;p=next[p])
const int INF=~0U>>2;
const int maxn=1005;
typedef
long long int64;
//
int L[maxn],R[maxn];
int ans[maxn];
int S1[maxn],S2[maxn];
char c;
void gcd(int a[],int b[]);
int equal(int a[],int b[]);
void sub(int a[],int b[]);//c=a-b
void copy(int a[],int b[]){DFOR(i,a[0],0)a[i]=0;FOR(i,0,b[0])a[i]=b[i];}//a=b
void div2(int a[]);//a/=2
void tim2(int a[]);//a*=2;
int main(){
freopen(
"bian.in","r",stdin);
freopen(
"bian.out","w",stdout);
int a[10],b[10];
MM(ans,
0),MM(L,0),MM(R,0),MM(a,0),MM(b,0);
for(;;){
scanf(
"%c",&c);
if(48<=c&&c<=49)L[0]++,L[L[0]]=c-48;
else break;
}

FOR(i,
1,L[0]/2)swap(L[i],L[L[0]-i+1]);
for(;scanf("%c",&c)!=EOF;){
if(48<=c&&c<=49)R[0]++,R[R[0]]=c-48;
else break;
}

FOR(i,
1,R[0]/2)swap(R[i],R[R[0]-i+1]);
gcd(L,R);
DFOR(i,ans[
0],1)printf("%d",ans[i]);
}

void show(int a[]){DFOR(i,a[0],1)printf("%d",a[i]);}
void gcd(int a[],int b[]){//a>=b
int t=equal(a,b);
if(t==2){gcd(b,a);return;}
else if(t==0){copy(ans,b);return;}
if(b[0]==1&&b[1]==1){copy(ans,b);return;}
if((b[0]==1||b[0]==0)&&b[1]==0){copy(ans,a);return;}
//
if(!(b[1]&1)&&!(a[1]&1)){div2(a),div2(b),gcd(a,b),tim2(ans);return;}
if((b[1]&1)&&(a[1]&1)){sub(a,b),gcd(a,b);return;}
if(!(b[1]&1)&&(a[1]&1)){div2(b),gcd(a,b);return;}
if((b[1]&1)&&!(a[1]&1)){div2(a),gcd(a,b);return;}
//
}

void sub(int a[],int b[]){
FOR(i,
1,b[0]){
a[i]
-=b[i];
while(a[i]<0)a[i]+=2,a[i+1]--;
}

FOR(i,
1,a[0])while(a[i]<0)a[i]+=2,a[i+1]--;
while(a[a[0]]<=0)a[0]--;
}

void div2(int a[]){
FOR(i,
1,a[0]-1)
a[i]
=a[i+1];
a[
0]--;
}

void tim2(int a[]){
DFOR(i,a[
0]+1,2)
a[i]
=a[i-1];
a[
1]=0;
a[
0]++;
}

int equal(int a[],int b[]){//1:a>b 2:a<b 0:a==b
if(a[0]>b[0])return 1;
else if(a[0]<b[0])return 2;
DFOR(i,a[
0],1)
if(a[i]>b[i])return 1;
else if(a[i]<b[i])return 2;
return 0;
}


第三题,并查集,运用拆点法,把它拆成,本身的集合和相对的集合两个部分。然后很水的。。
第二题不会fin的读入,所以用freopen,这个复制过来的。。。
#include<cstdio>
#include
<cstring>
#include
<iostream>
#include
<fstream>
#include
<algorithm>
using namespace std;
#define MM(a,i) memset(a,i,sizeof(a))
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define NFOR(i,a,b) for(i=a;i<=b;i++)
#define DFOR(i,b,a) for(int i=b;i>=a;i--)
#define NDFOR(i,b,a) for(i=b;i>=a;i--)
#define PFOR(p,head,next) for(int p=head;p;p=next[p])
#define NPFOR(p,head,next) for(p=head;p;p=next[p])
const int INF=~0U>>2;
const int maxn=50005;
typedef
long long int64;
int n,m;
int par[maxn*2],rank[maxn*2];
int ans=0;
int x,y,z;
int Getpar(int a){if(par[a]!=a)par[a]=Getpar(par[a]);return par[a];}
void Makeset(int a){par[a]=a;rank[a]=0;}
void Union(int a,int b){
a
=Getpar(a),b=Getpar(b);
if(rank[a]>rank[b])par[b]=a;
else {par[a]=b;
if (rank[a]==rank[b])rank[b]++;}

}

int main(){
freopen(
"str.in","r",stdin);
freopen(
"str.out","w",stdout);
scanf(
"%d %d",&n,&m);
FOR(i,
0,maxn*2-1)Makeset(i);
FOR(i,
1,m){
scanf(
"%d %d %d",&x,&y,&z);
if(z==0){
if(Getpar(x-1)==Getpar(y+maxn)){ans++;continue;}
Union(x
-1,y);
Union(x
-1+maxn,y+maxn);
}

else{
if(Getpar(x-1)==Getpar(y)){++ans;continue;}
Union(x
-1,y+maxn);
Union(x
-1+maxn,y);
}

}

printf(
"%d\n",ans);
return 0;
}

你可能感兴趣的:(SDOI-07-DAY2)