天與雲與山與水,上下一白
阿新 • • 發佈:2018-12-24
題目描述
t次詢問,每次給你一個數n,求在[1,n]內約數個數最多的數的約數個數
輸入描述:
第一行一個正整數t之後t行,每行一個正整數n
輸出描述:
輸出t行,每行一個整數,表示答案
#include <bits/stdc++.h>
using namespace std;
/* 暴力 素因子,沒什麼難度,
*/
typedef long long ll;
const int maxn=2000;
ll Stack[1000],top,Cnt[maxn];
int fenjie(ll k){
memset(Cnt,0,sizeof(Cnt));
top=0 ;
for(ll i=2;i*i<=k;i++){
while(k%i==0)
Cnt[top]++,k/=i;
Stack[top++]=i;
}
if(k>1){
Cnt[top]++;
Stack[top++]=k;
}
int rel=1;
for(int i=0;i<top;i++){
rel*=(Cnt[i]+1);
}
return rel;
}
ll s;
int main()
{ int t,a,b;
scanf("%d",&t);
while(t--){
scanf("%d%d",&a,&b);
int rel=-1;
int max1=-1;
for(int i=a;i<=b;i++){
int ans=fenjie(i);
if(ans>max1){
max1=ans;
rel=i;
}
}
printf ("%d\n",rel);
}
return 0;
}
但是這道題明顯不可以暴力,1e18的資料範圍。
但是我們可以使用質因子分解的逆過程。
首先,一個公式
一個數 s=pow(p1,j1)+pow(p2,j2)+…+pow(pn,jn).
一個數的因子個數=(j1+1)(j2+1)(j3+3)..
那麼我們可以列舉j1,j2,j3,並且保證最後的結果要小於等於n(這就要求一個引數),並且我們可以遞迴的計算因子個數。這樣就需要三個引數。
思想類似於爆搜。
但是這樣還是太慢了qwq,存在一個優化,那就是我們發現。
18=3*3*2.
12=2*2*3。
18和12有相同的分解結構,所以我們可以使其j陣列的數 隨著素因子的變大而變小,這樣會使其在相同的 分解結構中 有更小的總值。
參見部落格
https://www.cnblogs.com/acSzz/archive/2012/07/24/2606079.html
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
long long ans;
long long ansnum;//約數個數
long long n;
long long prime[30]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,51};
long long tt=2147483647;
//取20個質數
//2^a1 * 3^a2 * 5^a3 * 7^a4
bool solve(int s){
for(int i=2;i*i<=s;i++){
if(s%i==0)return 0;
}
return 1;
}
void dfs(long long m,long long pi,long long m_num,long long pre)//m為當前的數,pi為當前列舉的素數,m_num為m的約數的個數,pre為之前的素數的個數
{
if(m_num>ansnum)//更新最終結果
{
ans=m;
ansnum=m_num;
}
if(m_num==ansnum&&ans>m)//更新最終結果
{
ans=m;
}
for(long long l=1;l<=pre;)//m*(prime[pi]^l),這裡m不斷乘以當前列舉的素數,
{
if(n/m<prime[pi]) break;
m*=prime[pi];
if(m>n)
{
break;
}
l++;//計算當前素數被乘了多少次
dfs(m,pi+1,m_num*l,l-1);//此時m的素數的個數為m_num*l
}
}
int main()
{
long long total;
int cnk=0;
//cout<<LONG_MAX<<endl;
cin>>total;
while(total--)
{
ans=1;//最後結果的數
ansnum=-1;//最後的結果的約數的個數
scanf("%lld",&n);//n的輸入
//質數連乘開始
dfs(1,1,1,30);//初始時從1開始連乘,從第一個素數2開始,
printf("%lld\n",ansnum);
}
return 0;
}
題目描述
點點是一名出色的狼人。眾所周知,狼人只有在滿月之夜才會變成狼。 同時,月亮的大小隨著時間變化,它的大小變化30天為一迴圈。它的變化情況(從第一天開始)為0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 然後又再一次迴圈。 今年夏天點點很無聊,於是開始看月亮。由於點點很忙,所以他只選擇一段連續的時間看月亮,並把月亮的大小記錄了下來。 現在,他告訴你他記錄下東西,讓你告訴他下一天(即點點記錄下的最後一天的第二天)的月亮是比前一天(即點點記錄下的最後一天)大還是小。
輸入描述:
給你一個正整數n表示點點記錄下的時間個數。下一行n個自然數表示點點記錄下的月亮大小。
輸出描述:
一個字串。如果下一天的比前一天的大則輸出”UP”如果下一天的比前一天的小則輸出”DOWN”如果無法判斷則輸出”-1”
示例1
輸入
5
3 4 5 6 7
輸出
UP
思路: 0和15特判就可以,但是遺漏了一個細節,那就是一個數也是可以判斷的。。當為15時必定下降,為0時必定上升
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
vector<int>q;
int m,n;
int main()
{ while(cin>>m){
q.clear();
int max1=-1;
for(int i=0;i<m;i++){
scanf("%d",&n);
q.push_back(n);
max1=max(max1,n);
}
int loc=-1;
for(int i=0;i<q.size();i++){
if(q[i]==max1)
loc=i;
}
if(m==1){
if(q[0]==0)
puts("UP");
else if(q[0]==15)
puts("DOWN");
else
puts("-1");
}
else{
if(q[m-1]==0||q[m-1]==15){
if(q[m-1]-q[m-2]<0){
puts("UP");
}
else
puts("DOWN");
}
else{
if(q[m-1]-q[m-2]<0){
puts("DOWN");
}
else
puts("UP");
}
}
}
return 0;
}