Hcode OnlineJudge
思路:由于 ,所以如果直接暴力dfs查找,也是不会超时的,一开始看成和不大于1e5,浪费了点时间
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,x;
int ans=0;
vector<vector<int>>a;
void dfs(int pos,int w){
if(pos==n){
if(w==x) ans++;
return ;//别忘记return,我谢谢你
}
for(int u:a[pos]){
if(w>x/u) continue;
dfs(pos+1,w*u);
}
}
signed main(){
cin>>n>>x;
a.resize(n);
for(int i=0;i<n;i++){
int t;
cin>>t;
a[i].resize(t);
for(int j=0;j<=t-1;j++)cin>>a[i][j];
}
dfs(0,1);
cout<<ans<<endl;
return 0;
}
Hcode OnlineJudge
题解:,首先,如果我们把<=k改成=k,那么就变成了长度为M的数组中选择N个数相加为k的方案数,这里是做了一点更改,也就是最后再做一个前缀和与滚动数组。
动态转移方程:ndp[j]+=dp[j-p];
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,k;
const long long mod=998244353;
void solve(){
cin>>n>>m>>k;
vector<int>dp(k+1);
vector<int>ndp(k+1);
// dp[i][j] 表示前 i 个数,和为 j 的方案数
// dp[i][j] = dp[i - 1][k], k < j
dp[0]=1;
for(int i=1;i<=n;++i){
for(int j=i;j<=min(k,i*m);++j){
ndp[j]=0;
for(int p=1;p<=m&&j-p>=i-1;++p){
ndp[j]+=dp[j-p];
ndp[j]%=mod;
}
}
swap(dp,ndp);
}
int ans=0;
for(int j=n;j<=min(n*m,k);j++){
ans=(ans+dp[j])%mod;
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
while(t--){
solve();
}
return 0;
}
Hcode OnlineJudge
题解:每个位置各个数字等可能的情况:10^n
不存在0和不存在9的情况:9^n
0,9同时不存在的情况:8^n
所以0,9,同时存在的情况有(10^n-(2*9^n-8^n))%mod,最后注意一下负数取余就行
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 5, mod = 1e9 + 7;
int n;
int qm(int x,int p){
int re=1;
while(p){
if(p&1) re=re*x%mod;
x=x*x%mod;
p>>=1;
}
return re;
}
signed main() {
cin>>n;
cout<<(qm(10,n)-(2*qm(9,n)-qm(8,n))%mod+mod)%mod;
return 0;
}
Hcode OnlineJudge
题解:我们可以设置一个二维数组dp[N][10],dp[i][j]代表前i个操作产生结果为j的结果总数
动态转移方程就是
dp[i + 1][(j + a[i + 1]) % 10] = (dp[i][j] + dp[i + 1][(j + a[i + 1]) % 10]) % mod;
dp[i + 1][(j * a[i + 1]) % 10] = (dp[i][j] + dp[i + 1][(j * a[i + 1]) % 10]) % mod;
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,k;
int dp[100010][10];
const long long mod=998244353;
void solve(){
cin>>n;
vector<int> a(n+10);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
memset(dp, 0, sizeof(dp));
dp[1][a[1]] = 1;
for (int i = 1; i <= n - 1; i++)
{
for (int j = 0; j <= 9; j++)
{
dp[i + 1][(j + a[i + 1]) % 10] = (dp[i][j] + dp[i + 1][(j + a[i + 1]) % 10]) % mod;
dp[i + 1][(j * a[i + 1]) % 10] = (dp[i][j] + dp[i + 1][(j * a[i + 1]) % 10]) % mod;
}
}
for (int k = 0; k < 10; k++)
{
cout << dp[n][k] % mod << endl;
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
while(t--){
solve();
}
return 0;
}
Hcode OnlineJudge
题解:
首先分析一下,答案的区间。显然是[0,N]
所以如果每个元素的值不在这个区间内,那么它是不起作用的。
因此,第11个元素最多起作用n+1次,第22个元素n/2+1次,...,第N个元素2次。
本题的做法就是先找到每个元素起作用的区间[l,r],然后计算对应的值。设置M个vector,存储在每一次中出现的值。最后遍历一下即可。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 200010;
int n, m;
int a[N];
vector<int> f[N];
int main()
{
cin>>n>>m;
for(int i = 1; i <= n; i ++) cin>>a[i];
for(int i = 1; i <= n; i ++) {
if(a[i] >= n) continue;
int l,r;
if(a[i]>=0) l=1;
else l=(-a[i]-1)/i+1;
r = min(m + 1, (n - a[i] - 1) / i + 1);
for(int j = l; j < r; j ++) {
f[j].push_back(a[i] + i * j);
}
}
for(int i = 1; i <= m; i ++) {
int x = 0;
sort(f[i].begin(), f[i].end());
f[i].erase(unique(f[i].begin(), f[i].end()), f[i].end());//去重
if(!f[i].size()) {
cout<<0<<endl;
continue;
}
bool flag = false;
for(auto p : f[i]) {
if(p != x) {
flag = true;
cout<<x<<endl;
break;
}
x ++;
}
if(!flag) cout<<x<<endl;
}
return 0;
}