SGU 乱搞日志
SGU 100 A+B :太神不会
SGU 101 Domino:
题目大意:有N张骨牌,两张骨牌有两面有0到6的数字,能相连当且仅当前后数字相同,问能否有将N张骨牌连接的方案?思路:裸的欧拉回路,注意自环,连通
1 //sgu101 2 #include<iostream> 3 #include<cstdio> 4 #include <math.h> 5 #include<algorithm> 6 #include<string.h> 7 #include<queue> 8 #define MOD 1000003 9 #define maxn 2009 10 using namespace std; 11 int head[maxn],ans[maxn],top,now=1,next[maxn],point[maxn]; 12 int degree[maxn],sum=0; 13 bool visit[maxn],ss[maxn],sign[maxn]; 14 void add(int x,int y,bool si){ 15 next[++now]=head[x];head[x]=now; 16 point[now]=y;ss[now]=si; 17 } 18 void dfs(int s){ 19 for(int i=head[s];i;i=next[i])if(!visit[i>>1]){ 20 sum++; 21 int u=point[i];visit[i>>1]=1;dfs(u); 22 ans[++top]=i>>1;sign[top]=ss[i]; 23 } 24 } 25 int main() 26 { 27 int n,x,y,cnt=0,s=0; 28 scanf("%d",&n); 29 for(int i=1;i<=n;i++){ 30 scanf("%d%d",&x,&y);add(x,y,1);add(y,x,0); 31 degree[x]++;degree[y]++;s=x; 32 } 33 for(int i=0;i<=6;i++)if(degree[i]&1)cnt++,s=i;dfs(s); 34 if(sum!=n ||cnt>2){printf("No solution\n");return 0;} 35 for(int i=top;i>=1;i--){ 36 printf("%d ",ans[i]); 37 if(sign[i]==1)printf("+\n");else printf("-\n"); 38 } 39 return 0; 40 }
SGU 102 Coprimes:
题目大意:求小于n与n互质的数的个数 思路:欧拉函数哪家强
1 //sgu101 2 #include<iostream> 3 #include<cstdio> 4 #include <math.h> 5 #include<algorithm> 6 #include<string.h> 7 #include<queue> 8 #define MOD 1000003 9 #define maxn 2009 10 using namespace std; 11 int phi(int n) 12 { 13 int ret=n; 14 for(int i=2;i*i<=n;i++) 15 { 16 if(n%i==0)ret=(ret/i)*(i-1); 17 while(n%i==0)n/=i; 18 } 19 if(n>1)ret=ret/n*(n-1); 20 return ret; 21 } 22 int main() 23 { 24 int n; 25 scanf("%d",&n); 26 printf("%d\n",phi(n)); 27 return 0; 28 }
SGU 103 Traffic Lights
题目大意: 给一个无向图,每个节点有一个红绿灯(难道俄罗斯的灯是蓝紫灯?)灯会变换,能通过一条路当且仅当在通过前两个灯的颜色一样,问从s到t的最短时间是多少 思路:裸的SPFA,问题就是当不能通过时你得输出0!!!不然就会死在第6个点
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<cstring> 5 #define maxn 50000 6 using namespace std; 7 int tic[maxn],tib[maxn],ci[maxn],ric[maxn],s,t,n,m,now=0; 8 int head[maxn],next[maxn],point[maxn],value[maxn],dist[maxn],pre[maxn],ans[maxn]; 9 char ch[100]; 10 int col(int now,int l) 11 { 12 if(now<ric[l])return ci[l]; 13 now-=ric[l]; 14 int u,flag=0; 15 if(ci[l])u=tic[l];else u=tib[l]; 16 if(now%(tib[l]+tic[l])>=u)return ci[l];else return ci[l]^1; 17 } 18 int remai(int now,int l) 19 { 20 if(now<ric[l])return ric[l]-now; 21 now=(now-ric[l])%(tic[l]+tib[l]); 22 int u; 23 if(ci[l])u=tic[l];else u=tib[l]; 24 if(u-now>0)return u-now;else return tic[l]+tib[l]-now; 25 } 26 int tim(int now,int l,int r,int k) 27 { 28 if(k==4)return -1; 29 int u=col(now,l),v=col(now,r); 30 if(u==v)return 0; 31 u=remai(now,l);v=remai(now,r); 32 if(u==v) 33 { 34 int uu=tim(now+u,l,r,k+1); 35 if(uu==-1)return -1;else return u+uu; 36 } 37 else return min(u,v); 38 } 39 void add(int x,int y,int v) 40 { 41 next[++now]=head[x]; 42 head[x]=now; 43 point[now]=y; 44 value[now]=v; 45 } 46 int spfa(int s,int t) 47 { 48 memset(dist,-1,sizeof(dist)); 49 dist[s]=0; 50 int visit[maxn]={0}; 51 visit[s]=1; 52 queue<int>q; 53 q.push(s); 54 while(!q.empty()) 55 { 56 int u=q.front(); 57 visit[u]=0; 58 q.pop(); 59 for(int i=head[u];i;i=next[i]) 60 { 61 int k=point[i]; 62 int cost=tim(dist[u],k,u,1); 63 if(cost==-1)continue;else cost+=value[i]; 64 if(dist[u]+cost<dist[k] || dist[k] == -1) 65 { 66 pre[k]=u; 67 dist[k] = dist[u] + cost; 68 if(!visit[k]) 69 { 70 visit[k] = 1; 71 q.push(k); 72 } 73 } 74 } 75 } 76 if(dist[t]==-1)return 0;else return dist[t]; 77 } 78 int main() 79 { 80 int s,t,x,y,v,h=0; 81 scanf("%d%d%d%d",&s,&t,&n,&m); 82 for(int i=1;i<=n;i++) 83 { 84 scanf("%s%d%d%d",ch+1,&ric[i],&tib[i],&tic[i]); 85 if(ch[1]=='B')ci[i]=1;else ci[i]=0; 86 } 87 for(int i=1;i<=m;i++) 88 { 89 scanf("%d%d%d",&x,&y,&v); 90 add(x,y,v); 91 add(y,x,v); 92 } 93 printf("%d\n",spfa(s,t)); 94 int u=t; 95 while(pre[u]!=0) 96 { 97 ans[++h] = u; 98 u = pre[u]; 99 } 100 ans[++h]=s; 101 for(int i=h;i>=2;i--) 102 { 103 printf("%d ",ans[i]); 104 } 105 printf("%d\n",ans[1]); 106 return 0; 107 }
SGU 104 Little shop of flowers
题目大意:有V个花瓶,F束花,F束花只能按一定顺序插入花瓶,并且插入某个花瓶的美感度是固定的,问美感读最大是多少 思路:裸dp,转移方程在代码里,加个转移就好了
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 //dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+a[i][j]); 5 int dp[200][200],a[200][200],ans[200]; 6 bool pre[200][200]; 7 int main() 8 { 9 int f,v; 10 scanf("%d%d",&f,&v); 11 for(int i=1;i<=f;i++) 12 { 13 for(int j=1;j<=v;j++) 14 { 15 scanf("%d",&a[i][j]); 16 } 17 } 18 for(int i=1;i<=f;i++) 19 { 20 dp[i][0]=-0x3f3f3f3f; 21 for(int j=1;j<=v;j++) 22 { 23 if(dp[i][j-1]>dp[i-1][j-1]+a[i][j]) 24 { 25 dp[i][j]=dp[i][j-1]; 26 pre[i][j]=1; 27 } 28 else 29 { 30 dp[i][j]=dp[i-1][j-1]+a[i][j]; 31 pre[i][j]=0; 32 } 33 } 34 } 35 printf("%d\n",dp[f][v]); 36 int u=f,h=0; 37 for(int i=v;i>=1;i--) 38 { 39 if(!pre[u][i]) 40 { 41 u--; 42 ans[++h]=i; 43 } 44 if(u==0)break; 45 } 46 for(int i=h;i>=h-f+1;i--) 47 { 48 printf("%d ",ans[i]); 49 } 50 return 0; 51 }
SGU 105 Div 3
题目大意:给你 1 12 123...12345678910...的数列,问你前n个数中有多少能被3整除?思路:能被三整除的数当且仅当所有十进位数的和能被3整除,于是就能用等差数列求和乱搞了
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 int main() 5 { 6 long long n; 7 while (scanf("%I64d",&n)!=EOF) 8 { 9 long long u=n/3; 10 u<<=1; 11 if((n+1)%3==0)u++; 12 printf("%I64d\n",u); 13 } 14 return 0; 15 }
SGU 107 987654321 problem
题目大意:有多少N位十进制数的平方的尾数是987654321思路:暴力打表后发现9位数一共有8个数满足,因此无论多少位只要尾数是这8个数都OK,由于不能有前导0,因此9位数的情况单独考虑,本来以为要高精度来着,马上意识到答案是720000....的形式 sgu第一次这么善良
1 /* 2 111111111 12345678987654321 3 119357639 14246245987654321 4 380642361 144888606987654321 5 388888889 151234567987654321 6 611111111 373456789987654321 7 619357639 383603884987654321 8 880642361 775530967987654321 9 888888889 790123456987654321 10 */ 11 #include<cstdio> 12 #include<iostream> 13 using namespace std; 14 int main() 15 { 16 int n; 17 scanf("%d",&n); 18 if(n<=8)printf("0"); 19 else if(n==9)printf("8"); 20 else 21 { 22 printf("72"); 23 for(int i=1;i<=n-10;i++)printf("0"); 24 } 25 puts(""); 26 return 0; 27 }
SGU108 Self-numbers 2
题目大意:一个数n的后继是这个数本身加上它十进制位所有的数字,但有些数不能成为任何数的后继,找出第N个这样的数字 思路:直接按照题目模拟会MLE啊啊啊啊,看了题解才想到一个数的后继最多只是这个数+64,然后给优化下
1 #include<cstdio> 2 int ans[100000],x,h; 3 bool flag[70]; 4 int f(int x) 5 { 6 int ans=x; 7 while(x!=0) 8 { 9 ans+=x%10; 10 x/=10; 11 } 12 return ans; 13 } 14 int main() 15 { 16 int n,k; 17 scanf("%d%d",&n,&k); 18 for(int i=1;i<=n;i++) 19 { 20 if(flag[i%64]==0) 21 { 22 ans[++h]=i; 23 } 24 flag[f(i)%64]=1; 25 flag[i%64]=0; 26 } 27 printf("%d\n",h); 28 for(int i=1;i<=k;i++) 29 { 30 scanf("%d",&x); 31 printf("%d ",ans[x]); 32 } 33 }
SGU 123 The sum 因为k很小,所以就考你会不会c语言
1 #include<iostream> 2 #include<cstdio> 3 #define maxn 1000 4 using namespace std; 5 long long fib[maxn],sum[maxn]; 6 int main() 7 { 8 int k; 9 fib[1]=fib[2]=1; 10 sum[1]=1;sum[2]=2; 11 for(int i=3;i<=50;i++) 12 { 13 fib[i]=fib[i-1]+fib[i-2]; 14 sum[i]=sum[i-1]+fib[i]; 15 } 16 cin>>k; 17 cout<<sum[k]; 18 return 0; 19 }
SGU 134 就是求一个树的重心
1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #define maxn 52010 6 #define LLD "%I64d" 7 using namespace std; 8 long long head[maxn],n,next[maxn],ans=1ll<<30; 9 long long ver[maxn],point[maxn],ans_num,siz[maxn],now; 10 bool visit[maxn]; 11 void add(int x,int y) 12 { 13 next[++now]=head[x]; 14 head[x]=now; 15 point[now]=y; 16 } 17 void dfs(int k) 18 { 19 visit[k]=1; 20 siz[k]=1; 21 long long v=0; 22 for(int i=head[k];i;i=next[i]) 23 { 24 int u=point[i]; 25 if(visit[u]==1)continue; 26 dfs(u); 27 siz[k]+=siz[u]; 28 v=max(v,siz[u]); 29 } 30 v=max(v,n-siz[k]); 31 if(v<ans) 32 { 33 ans_num=1; 34 ver[ans_num]=k; 35 ans=v; 36 } 37 else if(v==ans)ver[++ans_num]=k; 38 } 39 int main() 40 { 41 ans=1ll<<30; 42 now=0; 43 memset(visit,0,sizeof(visit)); 44 memset(head,0,sizeof(head)); 45 int x,y; 46 scanf(LLD,&n); 47 if(n==1)while(1); 48 for(int i=1;i<n;i++) 49 { 50 scanf("%d%d",&x,&y); 51 add(x,y); 52 add(y,x); 53 } 54 dfs(1); 55 sort(ver+1,ver+1+ans_num); 56 printf(LLD " "LLD"\n",ans,ans_num); 57 for(int i=1;i<ans_num;i++) 58 { 59 printf(LLD " ",ver[i]); 60 } 61 printf(LLD "\n",ver[ans_num]); 62 return 0; 63 }