Aaronson
Accepts: 607
Submissions: 1869
Time Limit: 4000/2000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
问题描述
给出一个不定方程x0+2x1+4x2+...+2mxm=nx_{0}+2x_{1}+4x_{2}+...+2^{m}x_{m}=nx0+2x1+4x2+...+2mxm=n, 找出一组解(x0,x1,x2,...,xm)(x_0,x_1,x_2,...,x_m)(x0,x1,x2,...,xm), 使得∑i=0mxi\displaystyle\sum_{i=0}^{m} x_ii=0∑mxi最小, 并且每个xix_ixi (0≤i≤m0 \le i \le m0≤i≤m)都是非负的.
输入描述
输入包含多组数据, 第一行包含一个整数TTT (1≤T≤105)(1 \le T \le 10^5)(1≤T≤105)表示测试数据组数. 对于每组数据: 第一行包含两个整数nnn和mmm (0≤n,m≤109)(0 \le n,m \le 10^9)(0≤n,m≤109).
输出描述
对于每组数据, 输出∑i=0mxi\displaystyle\sum_{i=0}^{m} x_ii=0∑mxi的最小值.
输入样例
10 1 2 3 2 5 2 10 2 10 3 10 4 13 5 20 4 11 11 12 3
输出样例
1 2 2 3 2 2 3 2 3 2
分析:
就是把n二进制分解,只不过有m这个限制。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<map>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const int N=1e5+9;
int a[N];
int num(int x,int m)
{
int t=0;
while(x){
if(x&1)a[t++]=1;
else a[t++]=0;
x>>=1;
}
int i=0,sum=0;
for(i=0;i<t&&i<=m;i++){
sum+=a[i];
}
int w=2;
for(;i<t;i++){
sum+=a[i]*w;
w<<=1;
}
return sum;
}
int main()
{
//freopen("f.txt","r",stdin);
int T;scanf("%d",&T);
int n,m;
while(T--){
scanf("%d%d",&n,&m);
printf("%d\n",num(n,m));
}
return 0;
}
Bellovin
Accepts: 428
Submissions: 1685
Time Limit: 6000/3000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
问题描述
Peter有一个序列a1,a2,...,ana_1,a_2,...,a_na1,a2,...,an. 定义F(a1,a2,...,an)=(f1,f2,...,fn)F(a_1,a_2,...,a_n)=(f_1,f_2,...,f_n)F(a1,a2,...,an)=(f1,f2,...,fn), 其中fif_ifi是以aia_iai结尾的最长上升子序列的长度. Peter想要找到另一个序列b1,b2,...,bnb_1,b_2,...,b_nb1,b2,...,bn使得F(a1,a2,...,an)F(a_1,a_2,...,a_n)F(a1,a2,...,an)和F(b1,b2,...,bn)F(b_1,b_2,...,b_n)F(b1,b2,...,bn)相同. 对于所有可行的正整数序列, Peter想要那个字典序最小的序列. 序列a1,a2,...,ana_1, a_2, ..., a_na1,a2,...,an比b1,b2,...,bnb_1, b_2, ..., b_nb1,b2,...,bn字典序小, 当且仅当存在一个正整数iii (1≤i≤n)(1 \le i \le n)(1≤i≤n)满足对于所有的kkk (1≤k<i)(1 \le k < i)(1≤k<i)都有ak=bka_k = b_kak=bk并且ai<bia_i < b_iai<bi.
输入描述
输入包含多组数据, 第一行包含一个整数TTT表示测试数据组数. 对于每组数据: 第一行包含一个整数nnn (1≤n≤100000)(1 \le n \le 100000)(1≤n≤100000)表示序列的长度. 第二行包含nnn个整数a1,a2,...,ana_1,a_2,...,a_na1,a2,...,an (1≤ai≤109)(1 \le a_i \le 10^9)(1≤ai≤109).
输出描述
对于每组数据, 输出nnn个整数b1,b2,...,bnb_1,b_2,...,b_nb1,b2,...,bn (1≤bi≤109)(1 \le b_i \le 10^9)(1≤bi≤109)表示那个字典序最小的序列.
输入样例
3 1 10 5 5 4 3 2 1 3 1 3 5
输出样例
1 1 1 1 1 1 1 2 3分析:
试几组数据就能发现要求的就是LIS
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<map>
#include<queue>
#include<vector>
using namespace std;
const int N=100000+9;
int a[N],d[N],g[N],n;
void LIS() //Nlog(N)
{
for(int i=1;i<=n;i++)g[i]=INF;
for(int i=0;i<n;i++){
int k=lower_bound(g+1,g+1+n,a[i])-g;
d[i]=k;
g[k]=a[i];
}
}
int main()
{
//freopen("f.txt","r",stdin);
int T;scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%d",&a[i]);
LIS();
for(int i=0;i<n-1;i++)printf("%d ",d[i]);
printf("%d\n",d[n-1]);
}
return 0;
}
1003 留坑待补
Dertouzos
Accepts: 76
Submissions: 1357
Time Limit: 7000/3500 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
问题描述
正整数xxx称为nnn的positive proper divisor, 当且仅当x∣nx | nx∣n并且1≤x<n1 \le x < n1≤x<n. 例如, 1, 2, 和3是6的positive proper divisor, 但是6不是. Peter给你两个正整数nnn和ddd. 他想要知道有多少小于nnn的整数, 满足他们的最大positive proper divisor恰好是ddd.
输入描述
输入包含多组数据, 第一行包含一个整数TTT (1≤T≤106)(1 \le T \le 10^6)(1≤T≤106)表示测试数据组数. 对于每组数据: 第一行包含两个整数nnn和ddd (2≤n,d≤109)(2 \le n, d \le 10^9)(2≤n,d≤109).
输出描述
对于每组数据, 输出一个整数.
输入样例
9 10 2 10 3 10 4 10 5 10 6 10 7 10 8 10 9 100 13
输出样例
1 2 1 0 0 0 0 0 4题解:
随便推导下, 令y=xd, 如果ddd是yyy的maximum positive proper divisor, 显然要求x是y的最小质因子. 令mp(n)表示nnn的最小质因子, 那么就有x \le mp(d)x≤mp(d), 同时有y < ny<n, 那么x≤⌊n−1d⌋x \le \lfloor \frac{n-1}{d} \rfloor于是就是计算有多少个素数xxx满足x≤min{mp(d),⌊n−1d⌋}x \le \min{mp(d), \lfloor \frac{n-1}{d} \rfloor}
当d比较大的时候, ⌊n−1d⌋\lfloor \frac{n-1}{d} \rfloor比较小, 暴力枚举xxx即可. 当ddd比较小的时候, 可以直接预处理出答案. 阈值设置到106∼107都可以过.
分析:自己写的时候超时,不知道怎么搞的,后来改了改过了,郁闷!
还可以像题解一样预处理出答案。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<map>
#include<queue>
#include<vector>
using namespace std;
const int N=1000000+9;
int n,d;
int p[N],cnt,g[N];
bool np[N];
void init()
{
memset(np,0,sizeof(np));
cnt=0;
for(int i=2;i<N;i++){
if(!np[i]){
p[cnt++]=i;
g[i]=i;
}
for(int j=0;j<cnt&&i*p[j]<N;j++){
np[i*p[j]]=1;
g[i*p[j]]=p[j];
if(i%p[j]==0)break;
}
}
}
int cal(int x)
{
int t=upper_bound(p,p+cnt,x)-p;
return t;
}
int main()
{
//freopen("f.txt","r",stdin);
init();
int T;scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&d);
n--;
if(n<d)printf("0\n");
else if(d>=N){
int num=n/d,t=-1;
for(int i=0;p[i]<=num;i++)if(d%p[i]==0){
t=p[i];break;
}
if(t==-1)printf("%d\n",cal(num));
else printf("%d\n",cal(t));
}
else{
int x=min(n/d,g[d]);
printf("%d\n",cal(x));
}
}
return 0;
}