A-链接:https://www.nowcoder.com/acm/contest/71/A
来源:牛客网
给定n个正整数,请找出其中有多少个数x满足:在这n个数中存在数y=kx,其中k为大于1的整数
输入描述:
第一行输入一个n
接下来一行输入n个正整数ai
输出描述:
输出符合条件个数
示例1
输入
5 1 2 3 4 5
输出
2
说明
5个数中1和2符合条件,1是后面每个数的因子,2是4的因子
备注:
1≤n,a≤1000000
询问一个a[i]=x的整数倍(>1倍)是否也在数列中,统计x的个数;
用类似筛法的写法,对于x,检查kx(k>1)是否为真,如果存在就累加所有的x,复杂度O(nlog(n));
1 #include <bits/stdc++.h> 2 using namespace std; 3 int z, n, v[1000020]; 4 int main() { 5 scanf("%d", &n); 6 for (int i = 0; i < n; i++) { 7 int x; 8 scanf("%d", &x); 9 v[x]++; 10 } 11 for (int i = 1; i <= 1000000; i++) { 12 for (int j = i + i; j <= 1000000; j += i) { 13 if (v[j] > 0) { 14 z += v[i]; 15 break; 16 } 17 } 18 } 19 printf("%d ", z); 20 }
B-链接:https://www.nowcoder.net/acm/contest/71/B
来源:牛客网
设s,t为两个字符串,定义f(s,t) = t的子串中,与s相等的串的个数。如f("ac","acacac")=3, f("bab","babab")=2。现在给出n个字符串,第i个字符串为si。你需要对,求出,由于答案很大,你只需要输出对 998244353取模后的结果。
输入描述:
第一行一个整数n。
接下来n行每行一个仅由英文字母构成的非空字符串,第i个字符串代表s
i
。
输出描述:
共n行,第i行输出
对 998244353取模的结果。
示例1
输入
1 BALDRSKYKirishimaRain
输出
1
备注:
1 ≤ n ≤ 10
6
,所有字符串的总长度不超过2*10
6
说实话有点想骂人了,浪费我这么长时间一直以为自己kmp写傻逼了,最后把cout<<endl换成cout<<' '就能过全部数据我。。。。。。
注意到除了长度最小的字符串S,只要比S大的那么这个i对应的那一行的输出必定是零,比S大或长度相同但内容不同自然不会匹配成功,有一个为零答案就是0;
然后再对S向所有的字符串都跑一遍kmp,复杂度是O(L),L为字符串总长度。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 const int MAXN=1000010; 5 int MOD=998244353; 6 string str[MAXN],S; 7 int f[MAXN*2]; 8 int ans; 9 int main() 10 { 11 ios::sync_with_stdio(false); 12 cin.tie(0); 13 int n,i,j,k; 14 cin>>n; 15 cin>>str[1]; 16 S=str[1]; 17 for(i=2;i<=n;++i){ 18 cin>>str[i]; 19 if(str[i].length()<S.length()) 20 S=str[i]; 21 } 22 ans=1; 23 f[0]=-1; 24 j=-1; 25 for(i=1;i<=S.length();++i){ 26 j=f[i-1]; 27 while(j!=-1&&S[i-1]!=S[j])j=f[j]; 28 f[i]=j+1; 29 } 30 for(i=1;i<=n;++i){ 31 LL tmp=0; 32 int len=str[i].length(); 33 for(j=0,k=0;k<len;++k){ 34 if(S[j]==str[i][k]) j++; 35 else{ 36 while(j!=-1&&S[j]!=str[i][k])j=f[j]; 37 if(j!=-1&&S[j]==str[i][k])j++; 38 else j=0; 39 } 40 if(j==S.length()){j=f[j];tmp++;} 41 } 42 ans=(LL)ans*tmp%MOD; 43 if(!ans)break; 44 } 45 for(i=1;i<=n;++i){ 46 if(str[i]==S) 47 cout<<ans<<' '; 48 else 49 cout<<0<<' '; 50 } 51 return 0; 52 }
C-链接:https://www.nowcoder.com/acm/contest/71/C
来源:牛客网
小W在计算一个数列{An},其中A1=1,A2=2,An+2=An+1+An。尽管他计算非常精准,但很快他就弄混了自己的草稿纸,他找出了一些他计算的结果,但他忘记了这些都是数列中的第几项。
输入描述:
每行包括数列中的一项Ak(k<=100000)。
总行数T<=30。
输出描述:
对于每一项Ak,输出一行包括一个正整数k表示输入中数是数列的第几项。
示例1
输入
2 3 5 8 13
输出
2 3 4 5 6
显然要用到大数,但想要计算前十万个数并且保存一定MLE了,我们只留下最多40位末尾的数,显然这样的话末尾四十位的计算一定是正确的,而前100000项末尾四十位全部相同的几率是很小的,
大数一开始重载+莫名出bug,改成函数就好了。
1 #include<bits/stdc++.h> 2 using namespace std; 3 struct Bign 4 { 5 int a[50]; 6 Bign(){memset(a,0,sizeof(a));} 7 void print(){ 8 for(int i=a[0];i>=1;--i) 9 printf("%d",a[i]);puts(""); 10 } 11 }B[100005]; 12 Bign add(Bign A,Bign chs){ 13 int sz=max(A.a[0],chs.a[0]); 14 for(int i=1;i<=sz;i++){ 15 A.a[i]+=chs.a[i]; 16 if(A.a[i]>9){ 17 A.a[i+1]++; 18 if(i+1>sz) A.a[0]=++sz; 19 A.a[i]%=10; 20 } 21 } 22 return A; 23 } 24 bool ok(Bign A,Bign B){ 25 if(A.a[0]!=B.a[0]) return 0; 26 for(int i=1;i<=A.a[0];++i){ 27 if(A.a[i]!=B.a[i]) return 0; 28 } 29 return 1; 30 } 31 string s; 32 int main() 33 { 34 B[1].a[0]=B[2].a[0]=1; 35 B[1].a[1]=1; 36 B[2].a[1]=2; 37 for(int i=3;i<=100000;++i){ 38 B[i]=add(B[i-1],B[i-2]); 39 if(B[i].a[0]>40){ 40 for(int j=41;j<=B[i].a[0];++j) 41 B[i].a[j]=0; 42 B[i].a[0]=40; 43 } 44 } 45 //B[100000].print(); 46 while(cin>>s){//B[1000].print(); 47 Bign x; 48 int n=s.size(); 49 if(n>40)n=40; 50 reverse(s.begin(),s.end()); 51 x.a[0]=n; 52 for(int i=1;i<=n;++i) 53 x.a[i]=s[i-1]-'0'; 54 for(int i=1;;i++){ 55 if(ok(x,B[i])){ 56 cout<<i<<endl; 57 break; 58 } 59 } 60 } 61 return 0; 62 }