NOI**简单**英文题(抹汗😓)
#dfs为多元一次方程分配(决策)各变量的系数
Magic Sequence
#include <iostream>
#include <string.h>
using namespace std;
const int N=15;
int a[N];
int b[N];
int n;
int flag=0;
int vis[N];
void dfs(int s1,int s2,int cnt){
if(cnt==0){
if(s1==0&&s2==0){
// flag=1;
if(!flag){
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++){
b[i]=a[i];
vis[b[i]]++;
}
// for(int i=1;i<=n;i++){
// cout<<b[i]<<" ";
// }
// cout<<endl;
int j;
for(j=0;j<n;j++){
if(vis[j]!=a[j+1])break;
}
if(j==n)flag=1;
}
}
return;
}
for(int i=0;i<n;i++){
if(s1>=i&&s2>=i*(cnt-1)){
a[cnt]=i;
dfs(s1-i,s2-i*(cnt-1),cnt-1);
}
else break;
}
}
int main(){
cin>>n;
dfs(n,n,n);
if(flag){
for(int i=1;i<=n;i++){
cout<<b[i]<<endl;
}
}
return 0;
}
借鉴了下一题的dfs思想
能分解出n个因子的最小正整数
https://codeforces.com/problemset/problem/27/E
所以每个质数的系数对因子数量贡献是等价的,因此,相同的因子数要想得到尽可能小的数字,肯定是小的质数次数比较大。又由于前16个质因数相乘已经大于1e18了,所以只考虑前16个质因数即可。由于数据范围很小,直接dfs选出每个质因数的次数,筛选出最小的结果即可。
由于ans要设置得大于1e18,一定要unsigned long long
#include <iostream>
#include <math.h>
using namespace std;
typedef unsigned long long ll;//long long 过不了
//最坏的情况,前16个质数的幂次都为1,那前16个数相乘也将超过1e18
int p[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
ll ans=1e18+5;
ll n;
void dfs(ll now,ll cnt,int pos){
if(cnt==n){
ans=min(ans,now);
return ;
}
if(pos>=16)return;
for(int i=1;i<=60;i++){//对于每个质因数取多少次
now*=p[pos];
// cnt*=(1+i);
if(now>1e18||cnt*(1+i)>n)break;//这条路走不通了
dfs(now,cnt*(1+i),pos+1);
}
}
int main(){//能分解出n个因子的最小正整数n==(1+a1)*(1+a2)……
cin>>n;
dfs(1,1,0);
cout<<ans;
return 0;
}
coin change
本来是个典型的 恰好装满型的完全背包,写法见背包问题
但可以采用dfs的思想,
虽然但是,代码超时了,好歹学到了这种思想
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
// const int inf=0x3f3f3f;//要大于最小的,初始化为正无穷大
// INT_MAX 可以直接代替inf啦
int res=INT_MAX;//至少需要多少硬币
sort(coins.begin(),coins.end(),greater<int>());
dfs(coins,0,amount,0,res);
//后四个参数分别为,轮到枚举coins[turn]取几枚 ,
//总共还要取多少面值
//当下取了多少,全局最少取几枚
if(res==INT_MAX)return -1;
else return res;
}
void dfs(vector<int>& coins,int turn,int target,int ans,int& res){
if(turn>=coins.size())return;
//if(coins[turn]>target)return;
if(target%coins[turn]==0){//这才是一条路的终点,比较一条路的ans获得全局最小res
res=min(res,ans+target/coins[turn]);
return;
}
for(int i=target/coins[turn];i>=0;i--){//最多能取几枚该硬币
// 考虑到全局最优,不一定取得越多越好,so都要遍历
if(ans+i>=res-1)break;//下次肯定还要至少取一个
//res=min(res,ans+i); //res是各条路比较得到的一条路花的最少的硬币数ans,
// 这里还没有取到amount,这条路还没走完
dfs(coins,turn+1,target-i*coins[turn],ans+i,res);
}
}
};
Grocery Problem
整数的唯一分解定理
对于正整数n,仅存在一种方式将其分解成若干个质数幂次的乘积
X=
p
1
{p_1}
p1^
a
1
{a_1}
a1 *
p
2
{p_2}
p2^
a
2
{a_2}
a2 *
p
3
{p_3}
p3 ^
a
3
{a_3}
a3 *
…
…
……
……*
p
n
{p_n}
pn^
a
n
{a_n}
an
对于这类问题,一般采用试数的方法.操作过程是:把所有限制转换成为数学条件,然后逐一猜测答案并进行验算.而第一步:
转换为数学条件,直接关系到第二步验算的复杂程度.
首先对711000000做分解素因子处理
711000000
=
2
6
∗
3
2
∗
5
6
∗
79
711000000=2^6 *3^2 *5^6 *79
711000000=26∗32∗56∗79
这里最令人注目的数字莫过于79了.把79的倍数列表如下:
0
∗
79
=
0
,
1
∗
79
=
79
,
2
∗
79
=
158
,
3
∗
79
=
237
,
4
∗
79
=
316
,
5
∗
79
=
395
,
6
∗
79
=
474
,
7
∗
79
=
553
,
8
∗
79
=
632
,
9
∗
79
=
711
0*79=0,1*79=79,2*79=158,3*79=237,4*79=316, 5*79=395,6*79=474,7*79=553,8*79=632,9*79=711
0∗79=0,1∗79=79,2∗79=158,3∗79=237,4∗79=316,5∗79=395,6∗79=474,7∗79=553,8∗79=632,9∗79=711
由于在4种物品的价格中,必有一个物品的价格为79的倍数,也就是上表中的一个数,而和数711也为79的倍数,所以另外3种物
品的价格之和也为79的倍数.该关系表示如下:
711
=
(
9
∗
79
)
=
M
∗
79
+
N
∗
79
711=(9*79)=M*79+N*79
711=(9∗79)=M∗79+N∗79
这
里
,
M
∗
79
是
一
种
商
品
的
价
格
,
不
妨
令
A
=
M
∗
79
,
N
∗
79
是
另
3
种
商
品
价
格
之
和
,
不
妨
令
B
+
C
+
D
=
N
∗
79
这里,M*79是一种商品的价格,不妨令A=M*79,N*79是另3种商品价格之和,不妨令B+C+D=N * 79
这里,M∗79是一种商品的价格,不妨令A=M∗79,N∗79是另3种商品价格之和,不妨令B+C+D=N∗79
显然
M
+
N
=
9
M+N=9
M+N=9
下
面
我
们
来
筛
选
一
下
M
,
N
的
值
,
在
上
面
79
的
倍
数
表
中
,
因
为
不
能
有
3
个
数
都
小
于
100
,
所
以
N
≠
0
,
N
≠
1
,
这
样
M
≠
8
,
M
≠
9
而
7
并
未
出
现
于
711000000
的
素
因
子
集
合
中
,
所
以
下面我们来筛选一下M,N的值,在上面79的倍数表中,因为不能有3个数都小于100,所以N≠0,N≠1,这样M≠8,M≠9而7并未出现 于711000000的素因子集合中,所以
下面我们来筛选一下M,N的值,在上面79的倍数表中,因为不能有3个数都小于100,所以N=0,N=1,这样M=8,M=9而7并未出现于711000000的素因子集合中,所以M≠7,N≠2.
当
然
M
≠
0
是
显
而
易
见
的
,
所
以
N
≠
9.
至
此
,
M
可
以
取
的
值
为
1
,
2
,
3
,
4
,
5
,
6
,
当然M≠0是显而易见的,所以N≠9.至此,M可以取的值为1,2,3,4,5,6,
当然M=0是显而易见的,所以N=9.至此,M可以取的值为1,2,3,4,5,6,
#include <iostream>
#include <algorithm>
using namespace std;
int p[4];
int main(){
for(int x=1;x<=6;x++){
int i=79*x;
for(int j=1;j<711-i;j++){
for(int k=1;k<711-(i+j);k++){
int l=711-i-j-k;
if(i*j*k*l==711000000){
p[0]=i; p[1]=j;p[2]=k;p[3]=l;
sort(p,p+4);
for(int s=0;s<4;s++)cout<<p[s]<<" ";
// cout<<i<<" "<<j<<" "<<k<<" "<<l;
return 0;
}
}
}
}
return 0;
}
//1.0、
//#include <iostream>
//using namespace std;
//int main(){
// for(int i=1;i<711;i++){
// for(int j=1;j<711;j++){
// for(int k=1;k<711;k++){
// for(int l=1;l<711;l++){
// if(i+j+k+l==711&&i*j*k*l==711000000){
// cout<<i<<" "<<j<<" "<<k<<" "<<l;
// return 0;
// }
// }
// }
// }
// }
// return 0;
//}
//2.0
//#include <iostream>
//using namespace std;
//int main(){
// for(int i=1;i<711;i++){
// for(int j=1;j<711-i;j++){
// for(int k=1;k<711-(i+j);k++){
// int l=711-i-j-k;
// if(i*j*k*l==711000000){
// cout<<i<<" "<<j<<" "<<k<<" "<<l;
// return 0;
// }
// }
// }
// }
// return 0;
//}