浏览器标题切换
浏览器标题切换end

寒假Day16-蓝桥杯题4/7+POJ2135-Farm Tour(最小费用最大流模板题)

[蓝桥杯2019初赛]数列求值

给定数列1, 1, 1, 3, 5, 9, 17, …,从第4 项开始,每项都是前3 项的和。求
第20190324 项的最后4 位数字。

 

注意:

  • 遇到取后n位数,则%1000...(后面跟n个零);
  • 取后几位数字的时候,注意判断位数、输出前导零。

答案:4659

 

AC代码:

 1 #include<string.h>
 2 #include<iostream>
 3 #include<stdio.h>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<vector>
 7 #include<map>
 8 #include<cmath>
 9 using namespace std;
10 #define inf 0x3f3f3f3f
11 typedef long long ll;
12 
13 int a[20190333];
14 //int 4659  ll 4659
15 int main()
16 {
17     a[1]=1;
18     a[2]=1;
19     a[3]=1;
20     a[4]=3;
21     for(int i=5;i<=20190324;i++)
22     {
23         a[i]=a[i-1]+a[i-2]+a[i-3];
24         if(a[i]>10000)
25             a[i]%=10000;
26     }
27     int w=a[20190324];
28     if(w>=1000&&w<=9999)
29         cout<<w<<endl;
30     else
31     {
32         int wei=0,k=w;
33         while(k)
34             wei++,k/=10;
35         for(int i=1;i<=4-wei;i++)
36             cout<<"0";
37         cout<<w<<endl;
38     }
39     //w=4659
40     return 0;
41 }
View Code

 

WA代码:(不知道这样写为什么不对??)

 1 #include<string.h>
 2 #include<iostream>
 3 #include<stdio.h>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<vector>
 7 #include<map>
 8 #include<cmath>
 9 using namespace std;
10 #define inf 0x3f3f3f3f
11 const int N=110;
12 typedef long long ll;
13 
14 ll a[20190333];
15 //int 0691 ll 0115;
16 int main()
17 {
18     a[1]=1;
19     a[2]=1;
20     a[3]=1;
21     a[4]=3;
22     for(int i=5;i<=20190324;i++)
23         a[i]=a[i-1]+a[i-2]+a[i-3];
24     int w=a[20190324]%10000;
25     if(w>=1000&&w<=9999)
26         cout<<w<<endl;
27     else
28     {
29         int wei=0,k=w;
30         while(k)
31             wei++,k/=10;
32         for(int i=1;i<=4-wei;i++)
33             cout<<"0";
34         cout<<w<<endl;
35     }
36     return 0;
37 }
View Code

 

 


 

[蓝桥杯2019初赛]数的分解

把2019分解成3个各不相同的正整数之和,并且要求每个正整数都不包含数字2和4,一共有多少种不同的分解方法?
注意交换3个整数的顺序被视为同一种方法,例如1000+1001+18 和1001+1000+18 被视为同一种。

 

思路: i,j,k相加等于2019,接着把满足条件的存入数组中进行排序、标记判断即可。

 

注意:题看清楚,题面上给的所有要求都必须在代码中体现出来(仔细检查啊大哥!!!)

   像这种交换顺序题意说明还算是同一种的,可以利用排序进行判断,之后再开一个二维数组进行标记就可以嘞。

 

AC代码:

 1 #include<string.h>
 2 #include<iostream>
 3 #include<stdio.h>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<vector>
 7 #include<map>
 8 #include<cmath>
 9 using namespace std;
10 #define inf 0x3f3f3f3f
11 const int N=110;
12 typedef long long ll;
13 
14 int a[5];
15 bool book[2020][2020];
16 
17 int main()
18 {
19     ll ans=0;
20     memset(book,0,sizeof(book));
21     for(int i=1; i<=2019; i++)
22     {
23         for(int j=1; j<=2019; j++)
24         {
25             int k=2019-i-j;
26             if(i==j||i==k||j==k)
27                 continue;
28             if(k>0)
29             {
30                 a[0]=i;
31                 a[1]=j;
32                 a[2]=k;
33                 sort(a,a+3);
34                 int flag=0;
35                 for(int kk=0; kk<3; kk++)
36                 {
37                     flag=0;
38                     int t=a[kk];
39                     while(t)
40                     {
41                         int tt=t%10;
42                         t/=10;
43                         if(tt==2||tt==4)
44                         {
45                             flag=1;
46                             break;
47                         }
48                     }
49                     if(flag)
50                         break;
51                 }
52                 if(!flag&&!book[a[0]][a[1]])
53                 {
54                     book[a[0]][a[1]]=1;
55                     ans++;
56                 }
57             }
58         }
59     }
60     cout<<ans<<endl;
61     return 0;
62 }
View Code

 


 

 

[蓝桥杯2019初赛]立方和

 

 

注意:定义的数据范围啊,,,

int的2019的立方溢出了,需要改数据类型,老记不住到时候怎么错的都不知道,这么简单的也错,唉

(ull)i*i*i=2019*2019*2019

 

AC代码:

 1 #include<string.h>
 2 #include<iostream>
 3 #include<stdio.h>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<vector>
 7 #include<map>
 8 #include<cmath>
 9 using namespace std;
10 #define inf 0x3f3f3f3f
11 const int N=110;
12 typedef long long ll;
13 
14 int main()
15 {
16     unsigned long long ans=400816;
17     int flag=0;
18     for(unsigned long long i=41; i<=2019; i++)
19     {
20         int flag=0;
21         int kk=i;
22         while(kk)
23         {
24             int k=kk%10;
25             kk/=10;
26             if(k==2||k==0||k==1||k==9)
27             {
28                 flag=1;
29                 break;
30             }
31         }
32         if(flag)
33             ans=ans+i*i*i;
34     }
35     cout<<ans<<endl;
36     return 0;
37 }
View Code

 


POJ2135-Farm Tour(最小费用最大流模板题)

题面:

When FJ's friends visit him on the farm, he likes to show them around. His farm comprises N (1 <= N <= 1000) fields numbered 1..N, the first of which contains his house and the Nth of which contains the big barn. A total M (1 <= M <= 10000) paths that connect the fields in various ways. Each path connects two different fields and has a nonzero length smaller than 35,000.

To show off his farm in the best way, he walks a tour that starts at his house, potentially travels through some fields, and ends at the barn. Later, he returns (potentially through some fields) back to his house again.

He wants his tour to be as short as possible, however he doesn't want to walk on any given path more than once. Calculate the shortest tour possible. FJ is sure that some tour exists for any given farm.
Input
* Line 1: Two space-separated integers: N and M.

* Lines 2..M+1: Three space-separated integers that define a path: The starting field, the end field, and the path's length.
Output
A single line containing the length of the shortest tour.
View Code

样例:

Sample Input
4 5
1 2 1
2 3 1
3 4 1
1 3 2
2 4 2

Sample Output 6

 

题意:

 

给出n个点,m条边,问一个人从家走到barn的最短长度(设家1,barn为N);
所以,问的就是   去:1->N     和     返:N->1     两条路径的最短长度,两条路径不能重复;
所以,问题变成了:有两个人,从1->N,它们所走路径不能重复(走的边不能重复),求最短长度。

所以变成了最小费用最大流问题,自己再自己想想。

 

 

 思路:

我以为是个最短路。。但是最短路貌似好像不能解决路径重复问题叭。。

妥妥的模板,我终于碰到了,原来我先做的都是变形题,我太难了。。

题意转化到算法上还是比较不好想到,怎么分析在上面的题意里面已经写清楚了。

容量cap传入的为1或者2(自己判断传入什么),花费cost即点和点之间的权值。

 

建边最重要:

        memset(head,-1,sizeof(head));
        tot=0;
        s=0,t=n+1;
        for(int i=1;i<=m;i++)
        {
            int u,v,w;
            scanf("%d %d %d",&u,&v,&w);
            add(u,v,1,w);
            add(v,u,1,w);
        }
        add(s,1,2,0);
        add(n,t,2,0);
        printf("%d\n",MCMF());

 

AC代码:

  1 #include<string.h>
  2 #include<iostream>
  3 #include<stdio.h>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<vector>
  7 #include<map>
  8 #include<cmath>
  9 using namespace std;
 10 #define inf 0x3f3f3f3f
 11 const int N=1100;
 12 typedef long long ll;
 13 
 14 struct node
 15 {
 16     int to,nextt;
 17     int cap,flow,cost;
 18 } e[N*N];
 19 
 20 bool book[N];
 21 int pre[10*N],head[10*N],dist[N];
 22 int tot,s,t;
 23 
 24 void add(int u,int v,int cap,int cost)
 25 {
 26     e[tot].to=v;
 27     e[tot].cap=cap;
 28     e[tot].cost=cost;
 29     e[tot].flow=0;
 30     e[tot].nextt=head[u];
 31 
 32     head[u]=tot++;
 33     e[tot].to=u;
 34     e[tot].cap=0;
 35     e[tot].cost=-cost;
 36     e[tot].flow=0;
 37     e[tot].nextt=head[v];
 38     head[v]=tot++;
 39 }
 40 
 41 bool SPFA()
 42 {
 43     for(int i=0; i<=t; i++)
 44     {
 45         dist[i]=inf;
 46         book[i]=0;
 47         pre[i]=-1;
 48     }
 49     book[s]=1;
 50     dist[s]=0;
 51     queue<int>Q;
 52     Q.push(s);
 53     while(!Q.empty())
 54     {
 55         int u=Q.front();
 56         Q.pop();
 57         book[u]=0;
 58         for(int i=head[u]; i!=-1; i=e[i].nextt)
 59         {
 60             int v=e[i].to;
 61             if(e[i].cap>e[i].flow&&dist[v]>dist[u]+e[i].cost)
 62             {
 63                 dist[v]=dist[u]+e[i].cost;
 64                 pre[v]=i;
 65                 if(book[v]==0)
 66                 {
 67                     book[v]=1;
 68                     Q.push(v);
 69                 }
 70             }
 71         }
 72     }
 73     if(dist[t]!=inf)
 74         return 1;
 75     return 0;
 76 }
 77 
 78 int MCMF()
 79 {
 80     int flow=0,cost=0;
 81     while(SPFA())
 82     {
 83         int minn=inf;
 84         for(int i=pre[t]; i!=-1; i=pre[e[i^1].to])
 85             minn=min(minn,e[i].cap-e[i].flow);
 86         for(int i=pre[t]; i!=-1; i=pre[e[i^1].to])
 87         {
 88             e[i].flow+=minn;
 89             e[i^1].flow-=minn;
 90             cost+=e[i].cost*minn;
 91         }
 92         flow+=minn;
 93     }
 94     return cost;
 95 }
 96 
 97 int main()
 98 {
 99     int n,m;
100     while(~scanf("%d %d",&n,&m))
101     {
102         memset(head,-1,sizeof(head));
103         tot=0;
104         s=0,t=n+1;
105         for(int i=1;i<=m;i++)
106         {
107             int u,v,w;
108             scanf("%d %d %d",&u,&v,&w);
109             add(u,v,1,w);
110             add(v,u,1,w);
111         }
112         add(s,1,2,0);
113         add(n,t,2,0);
114         printf("%d\n",MCMF());
115     }
116     return 0;
117 }
View Code

 


 

待解决:

上面的数列求值中,为什么这样处理可以,

for(int i=5;i<=20190324;i++)
{
    a[i]=a[i-1]+a[i-2]+a[i-3];
    if(a[i]>10000)
        a[i]%=10000;
}

这样处理就不对,而且开ll和int出来结果也不一样,从后面溢出???可是不取余输出前面几位也不是正确答案啊???

for(int i=5;i<=20190324;i++)
    a[i]=a[i-1]+a[i-2]+a[i-3];
int w=a[20190324]%10000;

 

posted @ 2020-01-31 13:02  抓水母的派大星  阅读(182)  评论(0编辑  收藏  举报