立方数(cubic)
Time Limit:1000ms Memory Limit:128MB
题目描述
LYK定义了一个数叫“立方数”,若一个数可以被写作是一个正整数的3次方,则这个数就是立方数,例如1,8,27就是最小的3个立方数。
现在给定一个数P,LYK想要知道这个数是不是立方数。
当然你有可能随机输出一些莫名其妙的东西来骗分,因此LYK有T次询问~
输入格式(cubic.in)
第一行一个数T,表示有T组数据。
接下来T行,每行一个数P。
输出格式(cubic.out)
输出T行,对于每个数如果是立方数,输出“YES”,否则输出“NO”。
输入样例
3
8
27
28
输出样例
YES
YES
NO
数据范围
对于30%的数据p<=100。
对于60%的数据p<=10^6。
对于100%的数据p<=10^18,T<=100。
代码:纯暴力
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
using namespace std;
typedef long long ll;
ll T,x;
map <ll,bool> check;
int main()
{
freopen("cubic.in","r",stdin);
freopen("cubic.out","w",stdout);
scanf("%lld",&T);
for(ll i=0;i<=1e6;i++)
{
x=i*i*i;check[x]=1;
}
for(ll i=1;i<=T;i++)
{
scanf("%lld",&x);
if(check[x])cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
用二分查找函数会快一点
puts(lower_bound(check, check + 1000000, n) == n ? "YES" : "NO");
或者直接写二分避免卡stl
for(int i = 1; i <= n;i++) {
int flag = 0;
ll p = read();
int l = 1, r = 1000000;
while(l <= r) {
int mid = (l + r) >> 1;
if(a[mid] == p) {
flag = 1;
break;
}
else if(a[mid] > p) r = mid - 1;
else l = mid + 1;
}
if(flag) puts("YES");
else puts("NO");
}
立方数2(cubicp)
Time Limit:1000ms Memory Limit:128MB
题目描述
LYK定义了一个数叫“立方数”,若一个数可以被写作是一个正整数的3次方,则这个数就是立方数,例如1,8,27就是最小的3个立方数。
LYK还定义了一个数叫“立方差数”,若一个数可以被写作是两个立方数的差,则这个数就是“立方差数”,例如7(8-1),26(27-1),19(27-8)都是立方差数。
现在给定一个数P,LYK想要知道这个数是不是立方差数。
当然你有可能随机输出一些莫名其妙的东西,因此LYK有T次询问~
这个问题可能太难了…… 因此LYK规定P是个质数!
输入格式(cubicp.in)
第一行一个数T,表示有T组数据。
接下来T行,每行一个数P。
输出格式(cubicp.out)
输出T行,对于每个数如果是立方差数,输出“YES”,否则输出“NO”。
输入样例
5
2
3
5
7
11
输出样例
NO
NO
NO
YES
NO
数据范围
对于30%的数据p<=100。
对于60%的数据p<=10^6。
对于100%的数据p<=10^12,T<=100。
代码:
同t1;需要解释的是题目为了降低难度,给出p一定是质数,根据立方差公式有:
p=x^3-y^3=(x-y)(x^2+xy+y^2)
因为p是质数,根据质数定义,他的因子只有1和他本身,显然后面的式子大于1,所以(x-y)=1,(x^2+xy+y^2)=p;【结论:x=y+1,p=(x^2+xy+y^2)=3y^2+3y+1 , 为质数】
#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
typedef long long ll;
ll T,x,y,z,a;
map <ll,bool> check;
int main()
{
freopen("cubicp.in","r",stdin);
freopen("cubicp.out","w",stdout);
for(ll i=1;i<=999999;i++)
{
x=i; y=i+1;
z=x*x+x*y+y*y;
check[z]=1;
}
scanf("%lld",&T);
for(ll i=1;i<=T;i++)
{
scanf("%lld",&a);
if(check[a]==1) puts("YES");
else puts("NO");
}
return 0;
}
还是二分查找比较快,详见t1
猜数字(number)
Time Limit:2000ms Memory Limit:128MB
题目描述
LYK在玩猜数字游戏。
总共有n个互不相同的正整数,LYK每次猜一段区间的最小值。形如[li,ri]这段区间的数字的最小值一定等于xi。
我们总能构造出一种方案使得LYK满意。直到…… LYK自己猜的就是矛盾的!
例如LYK猜[1,3]的最小值是2,[1,4]的最小值是3,这显然就是矛盾的。
你需要告诉LYK,它第几次猜数字开始就已经矛盾了。
输入格式(number.in)
第一行两个数n和T,表示有n个数字,LYK猜了T次。
接下来T行,每行三个数分别表示li,ri和xi。
输出格式(number.out)
输出一个数表示第几次开始出现矛盾,如果一直没出现矛盾输出T+1。
输入样例
20 4
1 10 7
5 19 7
3 12 8
1 20 1
输出样例
3
数据范围
对于50%的数据n<=8,T<=10。
对于80%的数据n<=1000,T<=1000。
对于100%的数据1<=n,T<=1000000,1<=li<=ri<=n,1<=xi<=n(但并不保证一开始的所有数都是1~n的)。
Hint
建议使用读入优化
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == ‘-‘) f = -1;
for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - ‘0’;
return x * f;
}
总不能水一天吧,
所以长者就出了这么一个鬼畜t,让我卡了一下午才想过来;思路是二分+并查集(也可以用暴力模拟代替);
具体的:1。二分答案
2.把xi由大到小排序,那么就有(i > i-1,a[i] <= a[i-1])①a[i] < a[i-1]时,若新加入的线段(x~y)在之前已经被完全覆盖,则矛盾;②当a[i] = a[i-1]若两线段区间没有交集,则矛盾(因为有n个不同的数);
3.并查集操作f[]的代表元素是当前线段集合的最右点的再右一个,即rmax+1;处理并查集时,就看代表元素是否覆盖与否
4.lmin~rmax——并集;lmax~rmin——交集;
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1000000+10;
int T,n,li,ri,mid,ans,f[maxn],lmin,lmax,rmin,rmax;
struct node
{
int x,y,w;
}p[maxn],t[maxn];
inline int read()
{
int g=1,s=0; char ch=getchar();
while(ch>'9'||ch<'0'){ if(ch=='-') g=-1; ch=getchar();}
while(ch<='9'&&ch>='0'){ s=(s<<3)+(s<<1)+ch-'0'; ch=getchar();}
return g*s;
}
bool cmp(node a,node b)
{
return a.w>b.w;
}
int find(int now)
{
return now==f[now]?now:f[now]=find(f[now]);
}
bool check(int midd)
{
for(int i=1;i<=n+1;i++) f[i]=i;//之后要把代表元素设成右边一位,所以n+1
for(int i=1;i<=midd;i++) t[i]=p[i];
sort(t+1,t+1+midd,cmp);
lmin = lmax = t[1].x; rmin = rmax = t[1].y;//先把第一个放出来
for(int i=1;i<=midd;i++)
{
if(t[i].w < t[i-1].w)
{
if(find(lmax) > rmin) return true;//注意有后效性
for(int j=find(lmin);j<=rmax;j++)
f[find(j)] = find(rmax+1);//把区间代表元素设到rmax+1位
lmin = lmax =t[i].x; rmin = rmax = t[i].y;//后效性到for i+1是才会用到
}
else //t[i].w == t[i-1].w
{
lmin = min(lmin,t[i].x); lmax = max(lmax,t[i].x);
rmin = min(rmin,t[i].y); rmax = max(rmax,t[i].y);
if(rmin < lmax) return true;
}
}
if(find(lmax) > rmin) return true;//后效性 QAQ
return false;
}
int main()
{
n=read(); T=read();
for(int i=1;i<=T;i++) p[i].x=read(), p[i].y=read(), p[i].w=read();
li=1,ri=T,ans=T+1;
while(li<=ri)
{
mid=(ri+li)>>1;
if(check(mid)) ans=mid,ri=mid-1;
else li=mid+1;
}
printf("%d",ans);
return 0;
}