(1.) 换零钞
题意
钞票一共有(100、5、2、1)四种,现在有(2)张(100)元的钞票,去换零钱,要换出的零钱中(2)元的是(1)元的(10)倍,剩下的都是(5)元面额的
数据范围
无
题解
换的钱张数最少,即(1)元的最少,枚举(1)元的数目即可,然后得到(2)元的数目,最后判断一下剩余的金钱数能不能用(5)元的凑出来
Code
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int one=0;
int res=0;
for(int i=1;i<=200;i++)
{
if((200-i*2*10-i)%5==0)
{
one=i;
res=200-(i*2*10+i);
break;
}
}
int ans;
ans=one+10*one;
ans=ans+res/5;
printf("%d
",ans);
}
(2.) 激光样式
题意
(30)个灯,相邻的两个不能够同时亮,问一共能够有多少种不同的打开方式,全部关闭也算是一种
数据范围
(1leq nleq 30)
题解
暴力搜索所有可能的状态,全为(0)也算是一种
Code
#include<iostream>
using namespace std;
bool st[35];
int ans=0;
void dfs(int u,int pre){
if(u==31){
ans++;
return;
}
if(pre==0){
dfs(u+1,1);
}
dfs(u+1,0);
}
int main(){
dfs(1,0);
cout<<ans<<endl;
}
(3.) 格雷码
题意
代码填空,实现对一个数(x)求出其二进制下最右边的一个(1),并将其左边的二进制数字进行改变
数据范围
无
题解
(lowbit)操作能求出最右边的1,低位补(0)后的数字,将其左移一位置,即在后面加一个(0),求得的数字即当前最右边的(1)左边数字对应的数字为(1)的值,将原值与其异或后就可以求得改变后的数字
Code
x ^ (x&(-x)<<1)
(4.) 调手表
题意
给定(n)进制的手表,和一个(k),在任意时刻,有两个操作可以进行,(+1)或者(+k),手表只能显示(0sim n-1)的数字,
在最优策略下,求出从任意时间到达其他任意时间的操作数的最大值
数据范围
(0< k < n < 100000)
题解
因为是(mod)循环,可以看做是从(1)到(n-1)的所有最优方案,最小步数模型,(bfs)即可,所有步数的最大值即可。
Code
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<=n;i++)
const int N=1e5+10;
int n,k;
int ans;
int dist[N];
void bfs(){
memset(dist,-1,sizeof dist);
queue< int > q;
q.push(0);
dist[0]=0;
while(q.size()){
int t=q.front();
q.pop();
int tx=(t+1)%n,ty=(t+k)%n;
if(dist[tx]==-1){
dist[tx]=dist[t]+1;
ans=max(ans,dist[tx]);
q.push(tx);
}
if(dist[ty]==-1){
dist[ty]=dist[t]+1;
ans=max(ans,dist[ty]);
q.push(ty);
}
}
}
int main(){
scanf("%d%d",&n,&k);
bfs();
cout<<ans<<endl;
}
(5.) 搭积木
题意
输入一个(n,m),之后输入(n)行,每行(m)个字符表示当前是否可以放置,如果为(.)则可以放置,如果为(X)则不能放置,积木的放置必须满足以下三个规则,
-
当前可以防止积木当且仅当当前位置上一行放置了积木
-
每一行中积木的放置必须是连续的
默认第(0)行已经全部放置,求有多少种可能的放置方案,答案(mod; 10^{9}+7)
数据范围
(1leq n,mleq 10^{5})
题解
-
状态表示: (dp[i][l][r])在第(i)层的(lsim r)区间都放上积木的方案数
-
(lsim r)中能放上积木当且仅当(i-1)层中(lsim r)都已经放上了积木,否则就为(0)
-
当前行相同的放置,之前的行只要有不同的放置就算是不同的方案
-
-
状态转移:(dp[i][l][r] = sum_{j=1}^{l} sum_{k=r}^{m} dp[i-1][j][k])
- 当前的状态计算中不包含都不放的方案,所以答案的初始值需要设置为(1)
Code
#include<iostream>
using namespace std;
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define ll long long
const int mod=1000000007,N=110;
char g[N][N];
ll s[N][N],dp[N][N][N];
int c[N][N];
int n,m;
int ans;
void add_suffix(int i){
rep(j,1,m) rep(k,1,m){
s[j][k]=s[j-1][k]+s[j][k-1]-s[j-1][k-1]+dp[i][j][k];
}
}
ll get_suffix(int x1,int y1,int x2,int y2){
return (s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1])%mod;
}
int main(){
cin>>n>>m;
per(i,n,1) scanf("%s",g[i]+1);
rep(i,1,n)
rep(j,1,m)
c[i][j]=c[i][j-1]+(g[i][j]=='X');
dp[0][1][m]=1;
add_suffix(0);
int res=1;
rep(i,1,n){
rep(j,1,m){
rep(k,j,m){
if(c[i][k]-c[i][j-1]==0){
ll &x=dp[i][j][k];
x=(x+get_suffix(1,k,j,m))%mod;
res=(res+x)%mod;
}
}
}
add_suffix(i);
}
// rep(i,1,n){
// rep(j,1,m){
// cout<<dp[i][j]<<' ';
// }
// cout<<endl;
// }
cout<<(res+mod)%mod<<endl;
}
(6.) 矩阵求和
题意
给定一个(n),矩阵的每个位置((i,j))元素值等于(gcd(i,j)),求(n imes n)的矩阵的元素值之和
数据范围
(1leq nleq 10^{7})
题解
最大公约数(d)的范围为(1leq n)
-
对于(i,j in [d,n],gcd(i,j)=d)的个数
-
(i,jin [1,lfloor frac{n}{d} floor],gcd(i,j)=1)的数对的个数是一一对应的
-
满足(i<j),且(gcd(i,j)=1)的数对个数即(sum_{x=2}^{j} phi(x) + 1)
-
(i>j)时候个数上同(i<j)一样,二者都包含了((1,1))容斥掉即可
对于(iin [1,i-1])中与其互质的数的个数即欧拉函数(phi (i)),
Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
const int N=1e7+10,mod=1e9+7;
ll phi[N];
ll s[N];
bool st[N];
int primes[N],cnt;
void get_eulers(int n){
phi[1]=1;
for (int i = 2; i <=n ; ++i) {
if(!st[i]) {
primes[cnt++]=i;
phi[i]=i-1;
}
for (int j = 0; primes[j] <=n/i ; ++j) {
st[primes[j]*i]=true;
if(i%primes[j]==0) {
phi[primes[j]*i]=primes[j]*phi[i];
break;
}
phi[primes[j]*i]=phi[i]*(primes[j]-1);
}
}
s[1]=phi[1];
rep(i,2,n) s[i]=(s[i-1]+phi[i]*2)%mod;
}
// void get_eulers(int n){
// rep(i,2,n) phi[i]=0;
// phi[1]=1;
// for(int i=2;i<=n;i++){
// if(!phi[i]){
// for(int j=i;j<=n;j+=i){
// if(!phi[j]) phi[j]=j;
// phi[j]=phi[j]/i*(i-1);
// }
// }
// }
// s[1]=phi[1];
// rep(i,2,n) s[i]=(s[i-1]+phi[i]*2)%mod;
// }
int main(){
int n;
cin>>n;
get_eulers(n);
ll ans=0;
rep(d,1,n) ans=(ans+s[n/d]*d%mod*d)%mod;
cout<<ans<<endl;
}