[H题] 给你一个整数n,在1~n之间找到两个数i,j使得 i/gcd(i,j) 与j/gcd(i,j) 均为质数,问有多少个(i,j)?(1<=n<=1e7,时间限制:1s)
首先,素数打表,在打表的过程中,再定义一个数组用来存储1~n之间所有素数的某倍的个数,该数组的下标即是素数的倍数。
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int v[10000005],p[10000005],a[10000005]; 5 void prime(int n) 6 { 7 memset(v,0,sizeof(v)); 8 for(int i=2;i<=n;i++) 9 { 10 if(v[i]) continue; 11 for(int j=1;j<=n/i;j++) v[i*j]=1,a[j]++; 12 } 13 } 14 int main() 15 { 16 int n; 17 scanf("%d",&n); 18 prime(n); 19 ll ans=0; 20 for(int i=1;i<=n;i++) 21 { 22 ans+=(ll)(a[i]*(a[i]-1)); 23 } 24 printf("%lld ",ans); 25 return 0; 26 }
[A题] (0/1背包) 输入n代表数据的个数,接下来的n行里,输入pi,ai,ci,mi,gi(pi,ai,ci,mi相当于每个在p,a,c,m中所占的空间,gi代表价值)最后输入一行数据,包括P,A,C,M代表每个的总体积,求最大的价值,输出所选的个数以及路径(下标从0开始)(所有数据的范围均是1~36,时间限制:1s)
由于数据范围小,可直接五重循环写背包问题,但要注意用short类型的变量,否则内存超限!
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 typedef short int ss; 5 struct node 6 { 7 ss p,a,c,m,g,flag; 8 }mp[50]; 9 ss n,P,A,C,M; 10 ss f[50][50][50][50],pp[50][50][50][50][50],ans[100]; 11 int main() 12 { 13 // int ans=0; 14 // scanf("%d",&n); 15 cin>>n; 16 for(ss i=1;i<=n;i++) 17 // scanf("%d%d%d%d%d",&mp[i].p,&mp[i].a,&mp[i].c,&mp[i].m,&mp[i].g); 18 cin>>mp[i].p>>mp[i].a>>mp[i].c>>mp[i].m>>mp[i].g; 19 // scanf("%d%d%d%d",&P,&A,&C,&M); 20 cin>>P>>A>>C>>M; 21 ss j1,j2,j3,j4; 22 for(ss i=1;i<=n;i++) 23 for(j1=P;j1>=mp[i].p;j1--) 24 for(j2=A;j2>=mp[i].a;j2--) 25 for(j3=C;j3>=mp[i].c;j3--) 26 for(j4=M;j4>=mp[i].m;j4--){ 27 if(f[j1][j2][j3][j4]<f[j1-mp[i].p][j2-mp[i].a][j3-mp[i].c][j4-mp[i].m]+mp[i].g) 28 { 29 f[j1][j2][j3][j4]=f[j1-mp[i].p][j2-mp[i].a][j3-mp[i].c][j4-mp[i].m]+mp[i].g; 30 pp[i][j1][j2][j3][j4]=1; 31 } 32 } 33 34 ss cnt=0; 35 j1=P;j2=A;j3=C;j4=M; 36 for(ss i=n;i>=1;i--) 37 { 38 if(pp[i][j1][j2][j3][j4]==1) 39 { 40 ans[cnt++]=i-1; 41 j1-=mp[i].p; 42 j2-=mp[i].a; 43 j3-=mp[i].c; 44 j4-=mp[i].m; 45 } 46 } 47 // printf("%d ",cnt); 48 cout<<cnt<<endl; 49 for(ss i=cnt-1;i>=0;i--) 50 { 51 if(i!=cnt-1) cout<<" "; 52 cout<<ans[i]; 53 } 54 cout<<endl; 55 return 0; 56 }