中国(北方)大学生程序设计训练赛(第二周) (A B D G)
Posted wy_2016
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了中国(北方)大学生程序设计训练赛(第二周) (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\\n",t); 44 45 } 46 }
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 }
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=====\\n",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\\n",++kase,ans); 103 } 104 }
以上是关于中国(北方)大学生程序设计训练赛(第二周) (A B D G)的主要内容,如果未能解决你的问题,请参考以下文章