250
KleofasTail
题意:定义x的生成数列为 f(x)=x&1?x−1:x/2 ,给出K,L,R,询问有多少个位于L,R之间的数,它们的生成数列中至少出现一次K. 0≤L,R,K≤1018
分析:
观察发现生成数列中含有K的充要条件是二进制前缀与K相同(K为奇数),或者与K+1相同(K为奇数),因此只要枚举位数,算一下与L,R的交即可
500
FavouriteDigits
题意:求最小的>=N的数满足十进制表示中至少含有d1个c1和d2个c2 d1+d2≤15,N≤1015
分析:根据题目限制,显然答案小于 1015,因此只要数位dp搞搞就可以
1000
FleaCircus
题意:You are given a permutation Q. Count all permutations P such that P^4 = Q
分析:长度为n的循环的四次方的长度为n/gcd(n,4);根据这个结论,如果循环的大小是偶数k,那么对应的n=4k,否则n=k或者2k或者4k;对应的计数可以dp算算,复杂度O(n);也可以直接枚举2k和4k的;具体来说就是枚举其中一个特殊的循环是构成k的还是2k的还是4k的,对应的转移一下即可
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int M=1e9+9;
typedef long long LL;
const int Maxn=777;
class FleaCircus {
public:
vector<int>V;
int n;
int cnt[777];
bool done[777];
int F[777],G[777];
int C[777][777];
void getC(){
memset(C,0,sizeof(C));
for(int i=0;i0]=1;
for(int i=1;ifor(int j=1;j<=i;j++){
C[i][j]=(C[i-1][j]+C[i-1][j-1])%M;
}
}
}
void getF(){
memset(F,0,sizeof(F));
F[0]=F[4]=1;
for(int i=8;i4)F[i]=1LL*C[i-1][3]*F[i-4]%M;
memset(G,0,sizeof(G));
G[0]=G[2]=1;
for(int i=4;i2)G[i]=1LL*G[i-2]*(i-1)%M;
}
int powmod(int x,int y,int mod){
int ret=1;
while(y){
if(y&1)ret=1LL*ret*x%mod;
y>>=1;
x=1LL*x*x%mod;
}
return ret;
}
int cal(int x,int ty){
if(ty==4)return 1LL*x*x%M*x%M*6%M;
if(ty==2)return x;
if(ty==1)return 1;
return -1;
}
int solveodd(int x,int y){//x:geshu,y:val
int ret=0;
int t1=cal(y,4);
int t2=cal(y,2);
//printf("t1=%d t2=%d\n",t1,t2);
for(int i=0;i<=x;i+=4){
for(int j=0;j+i<=x;j+=2){
ret+=1LL*powmod(t1,i/4,M)*F[i]%M*powmod(t2,j/2,M)%M*G[j]%M*C[x][i]%M*C[x-i][j]%M;
ret%=M;
//printf("i=%d j=%d ret=%d\n",i,j,ret);
}
}
return ret;
}
int solveeven(int x,int y){//x:geshu ,y:val
int ret=1LL*F[x]*powmod(cal(y,4),x/4,M)%M;
return ret;
}
int countArrangements(vector<string> afterFourClicks) {
getC();
getF();
V.clear();
string s="";
for(int i=0;ifor(int j=0,k;jif(s[j]>='0'&&s[j]<='9'){
int t=0;
for(k=j;kisdigit(s[k]);k++){
t=t*10+s[k]-'0';
}
V.push_back(t);
j=k-1;
}
}
n=V.size();
memset(done,0,sizeof(done));
memset(cnt,0,sizeof(cnt));
for(int i=0;iif(!done[i]){
int tmp=0;
for(int j=i;!done[j];j=V[j])done[j]=1,tmp++;
cnt[tmp]++;
}
}
int ans=1;
for(int i=1;i<=n;i++){
if(!cnt[i])continue;
if(i&1){
ans=1LL*ans*solveodd(cnt[i],i)%M;
}
else{
if(cnt[i]%4)return 0;
ans=1LL*ans*solveeven(cnt[i],i)%M;
}
}
return ans;
return 0;
}
};