中国(北方)大学生程序设计训练赛(第二周) (A B D G)

比赛链接

A题是KMP,先把A拼接到B的后面,然后利用next数组的意义(包括其具体含义,以及失配时的应用),得到ans

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 char T[200005],S[200005];
 5 int tlen,slen;
 6 int Next[200005];
 7 
 8 void getNext()
 9 {
10     int j=0,k=-1;
11     Next[0]=-1;
12     while(j<tlen)
13         if(k==-1||T[j]==T[k])
14             Next[++j]=++k;
15         else
16             k=Next[k];
17 }
18 
19 int cal(int x)
20 {
21     int ret=0;
22     while(Next[x]!=-1)
23     {
24         x=Next[x];
25         ret++;
26     }
27     return ret;
28 }
29 
30 int main()
31 {
32     //freopen("test.txt","r",stdin);
33     int TT;scanf("%d",&TT);
34     while(TT--)
35     {
36         scanf("%s%s",S,T);
37         int x=min(strlen(S),strlen(T));
38         strcat(T,S);
39         tlen=strlen(T);
40         getNext();
41         int len=min(Next[tlen],x);
42         int t=cal(len);
43         printf("%d
",t);
44         
45     }
46 }
A

B算是数学题吧,对于同一个数,如果是整数,怎样操作都不会对difference有影响,而取ceil和取floor则恰好使difference差1,想明白这点就好了

代码自己没写,贴个链接。。 http://blog.csdn.net/mz839555819/article/details/47844275

D是DP,转移方程见代码

假设:当i'<i时,dp[i']都是确定好的最小的消耗值
1.当i为偶数时,dp[i]可能来自三个方向:i-1,i+1,i/2。若来自i+1,则i+1必然来自i+2,下面比较来自i+2和来自i/2的两种情况。
    dp[i]<-dp[i+2]+2x<-dp[(i+2)/2]+y+2x<-(dp[i/2]-x,dp[i/2]+x)+y+2x ;
    dp[i]<-dp[i/2]+y
显然后者得到的dp[i]更小,故i为偶数情况下,只可能从两个方向转移过来
2.当i为奇数时,dp[i]可能来自两个个方向:i-1,i+1。而i-1,i+1都是偶数,这样借用上面的偶数情况下的结论就可以了,即dp[i+1]只能由自己或是dp[(i+1)/2]转移过来。其中由dp[i]转移的情况推给dp[i-1]就好了

转移方程如下
  if(i&1) dp[i]=min(dp[i-1]+x,dp[(i+1)/2]+x+y)
  else dp[i]=min(dp[i-1]+x,dp[i/2]+y)

//最后,哪里有问题的话,欢迎提出来~
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 
 5 LL n,x,y,ans;
 6 LL dp[10000007];
 7 
 8 int main()
 9 {
10     //freopen("test.txt","r",stdin);
11     while(cin>>n>>x>>y)
12     {
13         memset(dp,0x3f3f3f3f,sizeof(dp));
14         ans=0;
15         dp[1]=x;dp[0]=0;
16         for(int i=2;i<=n+1;i++)
17         {
18             if(i&1)
19                 dp[i]=min(dp[i-1]+x,dp[(i+1)/2]+x+y);
20             else
21                 dp[i]=min(dp[i-1]+x,dp[i/2]+y);
22         }
23         cout<<dp[n]<<endl;
24     }
25 }
D

G题并查集,不同节点构成连通分量数 在这里等于 不同质因子的构成连通分量数。

具体一些细节: 1是特例; 只有质因子存在于图中时才要考虑该质因子

p.s. 分解质因数,素数筛 心里存个固定的板子真心好~

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long LL;
  4 
  5 const int N=1e6+3;
  6 int not_prime[N+5];
  7 vector<int> prime;
  8 bool vis[N+5];        //图中存在label,使i是label的质因数 
  9 bool done[N+5];        //这一连通分量是否已被计数 
 10 int p[N+5];
 11 int T,kase;
 12 
 13 int Find(int x)
 14 {
 15     return x==p[x]? x:p[x]=Find(p[x]);
 16 }
 17 void Union(int x,int y)
 18 {
 19     x=Find(x),y=Find(y);
 20     p[x]=y;
 21 }
 22 
 23 void init()
 24 {
 25     for(int i=2;i<=N;i++)
 26     {
 27         if(!not_prime[i])
 28         {
 29             //printf("%d=====
",i);
 30             prime.push_back(i);
 31             for(LL j=(LL)i*i;j<=N;j+=i)
 32                 not_prime[j]=true;
 33         }
 34     }
 35 }
 36 int init1()
 37 {
 38     for(int i=1;i<=N;i++)
 39         p[i]=i;
 40     memset(vis,false,sizeof(vis));
 41     memset(done,false,sizeof(done));
 42 }
 43 
 44 void getFactors(int x)
 45 {
 46     vector<int> a;
 47     for(int i=0;prime[i]*prime[i]<=x;i++)
 48     {
 49         if(x%prime[i]==0)
 50         {
 51             a.push_back(prime[i]),vis[prime[i]]=true;
 52             while(x%prime[i]==0) x/=prime[i];
 53         }
 54     }
 55     if(x>1) a.push_back(x),vis[x]=true;
 56     for(int i=1;i<a.size();i++)
 57         Union(a[0],a[i]);
 58 }
 59 
 60 int solve()
 61 {
 62     int ret=0;
 63     for(int i=0;i<prime.size();i++)
 64     {
 65         if(vis[prime[i]])
 66         {
 67             int t=Find(prime[i]);
 68             if(!done[t])
 69             {
 70                 ret++;
 71                 //printf("===%d====",t);
 72                 done[t]=true;
 73             }
 74         }
 75     }
 76     return ret;
 77 }
 78 
 79 int main()
 80 {
 81     init();
 82     //freopen("test.txt","r",stdin);
 83     scanf("%d",&T);
 84     while(T--)
 85     {
 86         init1();
 87         int ans=0; 
 88         int n;
 89         scanf("%d",&n);
 90         for(int i=0;i<n;i++)
 91         {
 92             int t;
 93             scanf("%d",&t);
 94             if(t==1)
 95             {
 96                 ans++;
 97                 continue; 
 98             }
 99             getFactors(t);
100         }
101         ans+=solve();
102         printf("Case %d: %d
",++kase,ans);
103     }
104 }
G
原文地址:https://www.cnblogs.com/Just--Do--It/p/6538388.html