时间限制: 1 Sec 内存限制: 512 MB
[提交] [状态]
题目描述
最大公约数GCD(a,b)是指a,b共有的因子中最大的那一个。比如说,GCD(12,18)=6,因为6既是12的因子,也是18的因子,而且不存在其他比6大的而且也是12,18的因子的数。
小明想知道如果给定n,m,对于1<=i<=n,GCD(i,m)的最大值是多少。
输入
第一行有两个用空格隔开的正整数n,m,含义见题目描述
输出
一行,只有一个整数,表示对于1<=i<=n,GCD(i,m)的最大值。
样例输入 Copy
【样例1】 4 6 【样例2】 5 10
样例输出 Copy
【样例1】 3 【样例2】 5
提示
样例1说明
可以按照GCD的定义求得GCD(1,6)=1 ;GCD(2,6)=2;GCD(3,6)=3;GCD(4,6)=2;所以答案为3
样例2说明
可以按照GCD的定义求得GCD(1,10)=1;GCD(2,10)=2;GCD(3,10)=1;GCD(4,10)=2;GCD(5,10)=5,所以答案为5
数据范围
对于60%的数据, 1<=n<=1000,1<=m<=1000
对于100%的数据,1<=n<=1e9,1<=m<=1e9
第一个的错误原因很明显了吧。。
然后考虑是不是dp来做呢?????
或者欧拉筛????
结果一个dfs就可以了,所以以后一定要计算一下复杂度。。。
2^30=1073741824(10位)
所以dfs不会超过30位。。。。。。。。
#include
using namespace std;
typedef long long ll;
int a[1000005];
int main()
{
int n,m,cnt=0;
cin>>n>>m;
int x=m;
for(int i=2;i*i<=m;i++)
{
while(x%i==0)
{
x/=i;
a[++cnt]=i;
}
if(x==1) break;
}
if(x!=1) a[++cnt]=x;
// printf("%d\n",cnt);
// for(int i=1;i<=cnt;i++)
// {
// printf("%d ",a[i]);
// }
int k=0;
a[0]=1;
while(m>n)
{
m/=a[k++];
}
printf("%d",m);
return 0;
}
/**************************************************************
Problem: 14998
User: 2019UPC110
Language: C++
Result: 答案错误
#include
using namespace std;
typedef long long ll;
ll a[1000005],vis[100005];
ll n,m,cnt=0,ans=0;
void dfs(ll n,ll m)
{
if(m<=ans) return ;
if(m<=n) {
ans=max(ans,m);
return;
}
for(int i=1;i<=cnt;i++)
{
if(vis[i]==0)
{
if(m%a[i]==0) vis[i]=1,dfs(n,m/a[i]);
vis[i]=0;
}
}
}
int main()
{
scanf("%lld%lld",&n,&m);
ll x=m;
for(int i=2; i*i<=m; i++)
{
while(x%i==0)
{
x/=i;
a[++cnt]=i;
}
if(x==1)
break;
}
if(x!=1) a[++cnt]=x;
dfs(n,m);
printf("%lld\n",ans);
return 0;
}
时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
Carol是一个爱学习的小朋友,他最近在读一本书,这本书的某些页十分晦涩难懂,需要阅读完另一页的内容才能完全理解。
而有些页则比较通俗易懂,阅读完当前页即可理解。
Carol是一个喜欢钻研的小朋友,他每天都会从这本书中页数最小的从未读过的一页开始读,读到完全理解这一页的内容为止。
例如对于当Carol某一天要读这本书的第a页时,这一页要求读完第b页才能理解,于是Carol又要去读第b页,而第b页要求读完第c页才能理解,于是Carol又要去读第c页,而第c页不需要读别的页就可以理解,或是需要读的页在之前已经读过了,最终Carol这一天读了a,b,c这三页内容。
Carol想知道自己需要花多少天才能读完这本书。
输入
第一行一个整数n,表示这本书有n页
第二行有n个正整数a1,a2,...,an,其中ai表示要读完第i页的内容要先读完第ai页的内容。(ai≥i)
输出
一个正整数,表示读完这本书需要的时间。
样例输入 Copy
【样例1】 6 1 3 3 5 6 6 【样例2】 10 3 4 3 4 8 7 8 10 10 10
样例输出 Copy
【样例1】 3 【样例2】 5
提示
样例1解释:
第一天Carol读了第一页,不需要再阅读其他页。
第二天Carol读了第二页,第二页要求读完第三页,于是他又读了第三页。
第三天Carol读了第四页,第四页要求读完第五页,第五页又要求读完第六页,于是他把这些页都读了。
样例2解释:
第一天Carol读了第1, 3页
第二天Carol读了第2, 4页
第三天Carol读了第5, 8, 10页
第四天Carol读了第6, 7页
第五天Carol读了第9页
对于20%的数据,ai=i
对于另外20%的数据,ai = min(i + 2, n)
对于所有数据,1≤n≤100000
#include
using namespace std;
typedef long long ll;
int f[1000005],vis[1000005];
void read(int k)
{
if(vis[k]==0) {
vis[k]=1;
read(f[k]);
}
}
int main()
{
int n,a;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a),f[i]=a;
int cnt=0;
for(int i=1;i<=n;i++)
{
if(vis[i]==0)
{
cnt++;
read(i);
}
}
printf("%d",cnt);
return 0;
}
时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
Bob最近沉迷于“雀魂”麻将,然而当他想做国士无双时却屡屡被断幺九截胡,所以他觉得事有蹊跷,于是复盘了一些玩家的手牌,看看他们有没有作弊。
Bob拿到的手牌是以字符串的形式给出的,字符串中依次给出了每一张牌的内容,每一张牌由两个字符构成,其规则如下:
1.麻将中一共有3*9+7=34种牌:
一条到九条,用t1到t9表示
一饼到九饼,用b1到b9表示
一万到九万,用w1到w9表示
东南西北中发白,分别用y1到y7表示
东南西北中发白,分别用y1到y7表示
2.每种牌最多有四个
3.每个人有且仅有十三张牌
输入
第1行1个正整数n(1≤n≤10000),表示有多少副手牌
第2行到第n+1行每行一个字符串s,表示手牌,字符串长度|s|≤1000
输出
n行
对于每副手牌,如果符合规则,就输出yes,否则输出no
样例输入 Copy
6 t1t9b1b9w1w9y1y2y3y4y5y6y7 t1t2t3t4t5t6t7t8t9y1y2y3y4 t111t2t3t4t5t6t7t8t9y1y2y3y4 t1t1t1t2t2t2t3t4t5t6t7t8t9 t1t1t1t1t2t2t2t2t3t4t5t6t7 b1b1b2b2b3b3b4b4b5b5b6b6b7b7b8b8b9b9
样例输出 Copy
yes yes no yes yes no
提示
说明
第三副牌中t111不是一张有效的牌,不在34种牌内
第六副牌有18张手牌
对于k%的数据,n≤10000∗(k/100)
#include
using namespace std;
typedef long long ll;
int main()
{
int n;
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
char str[10005];
scanf("%s",str);
int len=strlen(str);
int f=1;
if(len%2==1)
{
printf("no\n");
continue;
}
if((len+1)/2!=13)
{
printf("no\n");
continue;
}
int mp[100000]={0};
for(int i=0; i0)
mp[s]++;
//printf("%c%c : %d mp[s]:%d\n",str[i],str[i+1],s,mp[s]);
if(str[i]=='y')
{
if(mp[s]>4)
{
printf("no\n");
f=0;
break;
}
if(str[i+1]<'1'||str[i+1]>'7')
{
printf("no\n");
f=0;
break;
}
}
else if(str[i]=='t'||str[i]=='w'||str[i]=='b')
{
if(mp[s]>4)
{
printf("no\n");
f=0;
break;
}
if(str[i+1]<'1'||str[i+1]>'9')
{
printf("no\n");
f=0;
break;
}
}
else
{
printf("no\n");
f=0;
break;
}
}
if(f==1)
{
if((len+1)/2!=13)
printf("no\n");
else
printf("yes\n");
}
}
return 0;
}
时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
Francis最近在研究序列问题,他定义了这样一种操作:
如果序列中没有数, 则输出0
否则选择序列中最小的数,将它移出序列并输出它,再把序列中所有的数减去它的值Francis的序列中有n(n≤100000)个数,他要进行k(k≤100000)次操作,他想知道每次操作的输出,但是他发现这个问题太复杂了,于是他决定把问题交给你,让你帮他解决这个问题。
输入
第一行两个正整数n, k,表示序列有n个数,一共要进行k次操作
第二行n个整数a1,a2,a3...,an,分别表示序列中的n个数, 并且ai≤109
输出
n行,每行一个整数
第i行的整数表示第i次操作的输出
样例输入 Copy
【样例1】 5 5 4 7 8 10 3 【样例2】 2 5 1 4
样例输出 Copy
【样例1】 3 1 3 1 2 【样例2】 1 3 0 0 0
0
提示
样例1解释
初始序列4, 7, 8, 10, 3
第一次操作找到最小的数3,移出它并输出它,并让序列中所有的数减去3
序列变为1, 4, 5, 7
第二次操作找到最小的数1,移出它并输出它,并让序列中所有的数减去1
序列变为3, 4, 6
第三次操作找到最小的数3,移出它并输出它,并让序列中所有的数减去3
序列变为1, 3
第四次操作找到最小的数1,移出它并输出它,并让序列中所有的数减去1
序列变为2
第五次操作找到最小的数2,移出它并输出它,并让序列中所有的数减去2
样例2解释
初始序列1, 4
第一次操作找到最小的数1,移出它并输出它,并让序列中所有的数减去1
序列变为4
第二次操作找到最小的数4,移出它并输出它,并让序列中所有的数减去4
序列为空
后三次操作均输出0
对于p%的数据,n, k ≤ 100000 ∗ (p/100)
#include
using namespace std;
typedef long long ll;
int f[1000005],vis[1000005];
priority_queue, greater >q;
int main()
{
int n,m,kk=0;
cin>>n>>m;
for(int i=1;i<=n;i++)
{int a;scanf("%d",&a);q.push(a);}
int minn=min(n,m);
for(int i=0;in)
{
for(int i=n;i