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 }
View Code

 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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

 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 }
View Code

 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 }
View Code

 

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 }
View Code

 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 }
View Code

 

你可能感兴趣的:(SGU 乱搞日志)