E:
题目思路很清晰,只是不知道怎么在规定时间类很好的实现,后来看了代码,原来素数表还可以这样用,这次又学到一招,之后的二分写的也比较纠结,总的来说,整个代码的核心部分在于素数表。
ACcode:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int NS=1000100;
const int MS=10000010;
int n,t;
int a[MS],b[MS];
int minp[MS],pri[MS],pos[MS],top=0;
LL c[MS];
void prime_table()
{
for (int i=2;i<MS;i++)
{
if (!minp[i])
{
pri[top]=i;
pos[i]=top++;
for (int j=i;j<MS;j+=i)
if (!minp[j]) minp[j]=i;
}
// printf("minp[%d]=%d\n",i,minp[i]);
}
// printf("top=%d\n",top);
}
int main()
{
prime_table();
while (~scanf("%d",&n))
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
for (int i=0;i<n;i++)
scanf("%d",&t),a[t]++;
for (int i=MS-10;i>1;i--)
{
c[pos[minp[i]]]+=a[i]+b[i];
b[i/minp[i]]+=a[i]+b[i];
a[i-1]+=a[i];
}
LL temp,s,mid,down=1,up=10000000000000LL;
while (down<up)
{
t=1;
mid=(down+up)>>1;
for (int i=0;i<top;i++)
{
s=0,temp=mid;
while(temp>=pri[i]) temp/=pri[i],s+=temp;
if (s<c[i]) { t=0; break; }
}
if (t>0) up=mid;
else down=mid+1;
}
printf("%I64d\n",up);
}
return 0;
}
D:
题目意思很明确,不知道怎么做,看了cxlove的思路,用分治解决的,把四维分解成两个两维背包。
ACcode:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int NS=1005;
const int MOD=7340033;
LL dp[35][NS],tmp[NS];
void Init()
{
memset(dp,0,sizeof(dp));
dp[0][0]=dp[1][0]=1;
for (int i=1;i<=34;i++)
{
dp[i][0]=1;
memset(tmp,0,sizeof(tmp));
for (int j=0;j<=1000;j++)
for (int k=0;k<=1000-j;k++)
tmp[j+k]+=dp[i-1][j]*dp[i-1][k],
tmp[j+k]%=MOD;
for (int j=0;j<=1000;j++)
for (int k=0;k<=1000-j;k++)
dp[i][j+k+1]+=tmp[j]*tmp[k],
dp[i][j+k+1]%=MOD;
}
}
int main()
{
Init();
int q,n,k,h;
scanf("%d",&q);
while (q--)
{
scanf("%d %d",&n,&k);
for (h=0;n>1;n>>=1)
if (n&1) h++;
else break;
printf("%I64d\n",dp[h][k]);
}
return 0;
}