【寒假集训系列2.14】

摆脱了110魔咒...

30+100+0=130

诶呀第三题没开long long一分都没有啊...

T1Gcd

 

 

题目描述:

给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对.

输入:

一个整数N

输出:

如题

样例输入:

4

样例输出:

4

数据规模:

    30%:N<=5000

100%: N<=10^7

  这道题似乎以前听过啊...然而不太会诶,枚举gcd,然后找互质的数,突然一下子就忘记欧拉函数这个东西了...然后暴力于是30分

  正解:欧拉筛一下,求出欧拉函数,把所有互质的个数求出来,然后枚举gcd(),即质数,当然那些质数对(x,x)(x是质数)会被算两次,要减掉

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cstdlib>
 6 #include<ctime>
 7 #include<cmath>
 8 inline int read(){
 9     int ans=0,f=1;char chr=getchar();
10     while(!isdigit(chr)){if(chr=='-')f=-1;chr=getchar();}
11     while(isdigit(chr)) {ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
12     return ans*f;
13 }const int N=1e7+5;
14 int n,prime[N],p[N],cnt,phi[N];
15 long long sum[N],ans;
16 void pre(){
17     phi[1]=1;
18     for(int i=2;i<=n;++i){
19         if(prime[i]==0) 
20             p[++cnt]=i,phi[i]=i-1;
21         for(int j=1;j<=cnt;++j){
22             if(i*p[j]>n) break;
23             prime[i*p[j]]=1;
24             phi[i*p[j]]=(i%p[j]==0)?p[j]*phi[i]:phi[i]*(p[j]-1);//欧拉函数(积性函数)
25         }
26     }
27 }
28 int main(){
29 //    freopen("gcd.in","r",stdin);
30 //    freopen("gcd.out","w",stdout);
31     n=read();pre();
32     for(int i=1;i<=n;++i) sum[i]=sum[i-1]+phi[i];//前缀和
33     for(int i=1;i<=cnt;++i) ans+=sum[n/p[i]]*2;
34     printf("%lld\n",ans-cnt);//减掉质数对个数
35

T2宝藏

 

题目描述:

 

老胡在出模拟赛时想到了这样一道题:给出一个网格图,其中某些格子有宝物,每次从左上角出发,只能向下或右走,问至少走多少次才能将宝藏捡完。但这个问题对老胡来说太简单了,现在假设每个格子中有好多宝物,而每一次经过一个格子至多只能捡走一个,至少走多少次才能把宝物全部捡完。

 

输入:

 

第一行为正整数T,代表数据组数。

 

每组数据第一行为正整数N,M代表网格图有N行M列,接下来N行每行M个非负整数,表示此格子中宝物数量,0代表没有

 

输出:

 

 输出一个整数,表示至少要走多少次。

 

样例输入:

 

1

 

3 3

 

0 1 5

 

5 0 0

 

1 0 0

 

样例输出:

 

10

 

 

 

数据规模:

 

30%: N,M<=5

 

50%: N,M<=100

 

100%: N,M<=1000,每个格子中宝物数不超过10^6 

 

方法: Dilworth定理:DAG的最小链覆盖=最大点独立集

  然而半天过不了样例...i,j循环顺序打反了...不会的同学搜一下Dilworth定理吧(O3不开也可以)

 1 #pragma GCC optimize(3)//可以删掉,打读入优化的话完全不会TLE
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<iostream>
 6 #include<cstdlib>
 7 #include<ctime>
 8 #include<cmath>
 9 using namespace std;
10 inline int read(){
11     int ans=0,f=1;char chr=getchar();
12     while(!isdigit(chr)){if(chr=='-')f=-1;chr=getchar();}
13     while(isdigit(chr)) {ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
14     return ans*f;
15     int x;scanf("%d",&x);
16     return x;
17 }const int M=1005;
18 int n,m,f[M][M];
19 int main(){
20     freopen("treasure.in","r",stdin);
21     freopen("treasure.out","w",stdout);
22     int T=read();
23     while(T--){
24         n=read(),m=read();
25         for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)f[i][j]=read();
26         for(int j=1;j<=m;j++)
27             for(int i=n;i>0;i--)
28                 f[i][j]=max(f[i][j]+f[i+1][j-1],max(f[i][j-1],f[i+1][j]));
29         printf("%d\n",f[1][n]);
30     }
31     return 0;
32 }

 

T3配对

 

题目描述:

 

给出一棵n个点的树,将这n个点两两配对,求所有可行的方案中配对两点间的距离的总和最大为多少。

 

输入:

 

一个数n(n保证为偶数)。

 

接下来n-1行每行三个数x,y,z表示有一条长度为z的边连接x和y。

 

输出:

 

    一个数表示答案。

 

样例输入:

 

6

 

1 2 1

 

1 3 1

 

1 4 1

 

3 5 1

 

4 6 1

 

样例输出:

 

7

 

样例解释:

 

配对方案:1,2)(3,4)(5,6)

 

数据规模:

 

30%: N<=10

 

50%: N<=100

 

70%: N<=1000

 

100%: N<=10^5,z<=10^9

 

比赛的时候打了一个模拟退火+树剖(+线段树求距离)LCA(打算骗70分,噢真是可笑...),然后没开long long成功爆0,否则20分(应该是参数没调好)...

正解:分开对每一条边考虑:若是要总值最大,那么一条边被计算的次数越多越好,然后记录一下每个子树的大小,取该点子树大小和除去该子树数其他部分大小的min值

文字看不懂的话就看代码吧...出题人ciki表示这是一道智障题,然而没有一个人拿分?

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cstdlib>
 6 #include<ctime>
 7 #include<cmath>
 8 #define int long long
 9 using namespace std;
10 inline int read(){
11     int ans=0,f=1;char chr=getchar();
12     while(!isdigit(chr)){if(chr=='-')f=-1;chr=getchar();}
13     while(isdigit(chr)) {ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
14     return ans*f;
15 }const int M=1e5+5;
16 int n,x,y,z,p[M];
17 long long ans;
18 int head[M<<1],nxt[M<<1],ver[M<<1],val[M<<1],tot,sz[M];
19 inline void add(int x,int y,int z){ver[++tot]=y;val[tot]=z;nxt[tot]=head[x];head[x]=tot;}
20 const double delta=0.998,t_min=1e-14;
21 void dfs(int x,int fa){sz[x]=1;
22     for(int i=head[x];i;i=nxt[i]){int y=ver[i];
23         if(y==fa) continue;
24         dfs(y,x);sz[x]+=sz[y];
25         ans+=val[i]*min(sz[y],n-sz[y]);
26     }
27 }
28 signed main(){
29     freopen("match.in","r",stdin);
30     freopen("match.out","w",stdout);
31     n=read(); 
32     for(int i=1;i<n;i++){x=read(),y=read(),z=read();add(x,y,z),add(y,x,z);}
33     dfs(1,0);cout<<ans;
34     return 0;
35 }

 

posted @ 2019-02-14 14:11  zheng_liwen  阅读(117)  评论(0编辑  收藏  举报
/*去广告*/