1. 程式人生 > >【寒假集訓系列2.14】

【寒假集訓系列2.14】

cstring 數據 names etc pan 超過 個人 代碼 ios

擺脫了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 }

【寒假集訓系列2.14】